/* eslint-disable */
define( [ 'ueditorCore', 'constants', './xiuxiu' ], function( ueditorCore, constants ) {

  UE.I18N[ 'zh-cn' ] = {
    'labelMap': {
      'anchor': '锚点',
      'undo': '撤销',
      'redo': '重做',
      'bold': '加粗',
      'indent': '首行缩进',
      'snapscreen': '截图',
      'italic': '斜体',
      'underline': '下划线',
      'strikethrough': '删除线',
      'subscript': '下标',
      'fontborder': '字符边框',
      'superscript': '上标',
      'formatmatch': '格式刷',
      'source': '源代码',
      'blockquote': '引用',
      'pasteplain': '纯文本粘贴模式',
      'selectall': '全选',
      'print': '打印',
      'preview': '预览',
      'horizontal': '分隔线',
      'removeformat': '清除格式',
      'time': '时间',
      'date': '日期',
      'unlink': '取消链接',
      'insertrow': '前插入行',
      'insertcol': '前插入列',
      'mergeright': '右合并单元格',
      'mergedown': '下合并单元格',
      'deleterow': '删除行',
      'deletecol': '删除列',
      'splittorows': '拆分成行',
      'splittocols': '拆分成列',
      'splittocells': '完全拆分单元格',
      'deletecaption': '删除表格标题',
      'inserttitle': '插入标题',
      'mergecells': '合并多个单元格',
      'deletetable': '删除表格',
      'cleardoc': '清空文档',
      'insertparagraphbeforetable': "表格前插入行",
      'insertcode': '代码语言',
      'fontfamily': '字体',
      'fontsize': '字号 10~72px（可手动输入）',
      'paragraph': '段落',
      // sherlockl 'paragraph': '段落格式',
      'simpleupload': '单图上传',
      'insertimage': '换图',
      'edittable': '表格属性',
      'edittd': '单元格属性',
      'link': '超链接',
      'emotion': '表情',
      'spechars': '特殊字符',
      'searchreplace': '查询替换',
      'map': 'Baidu地图',
      'gmap': 'Google地图',
      'insertvideo': '视频',
      'help': '帮助',
      'justifyleft': '居左对齐',
      'justifyright': '居右对齐',
      'justifycenter': '居中对齐',
      'justifyjustify': '两端对齐',
      'forecolor': '字体颜色',
      'backcolor': '背景色',
      'insertorderedlist': '有序列表',
      'insertunorderedlist': '无序列表',
      'fullscreen': '全屏',
      'directionalityltr': '从左向右输入',
      'directionalityrtl': '从右向左输入',
      'rowspacingtop': '段前距',
      'rowspacingbottom': '段后距',
      'pagebreak': '分页',
      'insertframe': '插入Iframe',
      'imagenone': '默认',
      'imageleft': '左浮动',
      'imageright': '右浮动',
      'attachment': '附件',
      'imagecenter': '居中',
      'wordimage': '图片转存',
      'lineheight': '行间距',
      'edittip': '编辑提示',
      'customstyle': '自定义标题',
      'autotypeset': '自动排版',
      'webapp': '百度应用',
      'touppercase': '字母大写',
      'tolowercase': '字母小写',
      'background': '背景',
      'template': '模板',
      'scrawl': '涂鸦',
      'music': '音乐',
      'inserttable': '插入表格',
      'drafts': '从草稿箱加载',
      'charts': '图表',
      // sherlockl
      'qqmusic': '插入音乐',
      'synonyms': '近义词查询',
      'imgstyle': '图片边框阴影',
      'linebreak': '显示行标记',
      'imagesjustifycenter': '图片一键居中'
    },
    'insertorderedlist': {
      'num': '1,2,3...',
      'num1': '1),2),3)...',
      'num2': '(1),(2),(3)...',
      'cn': '一,二,三....',
      'cn1': '一),二),三)....',
      'cn2': '(一),(二),(三)....',
      'decimal': '1,2,3...',
      'lower-alpha': 'a,b,c...',
      'lower-roman': 'i,ii,iii...',
      'upper-alpha': 'A,B,C...',
      'upper-roman': 'I,II,III...'
    },
    'insertunorderedlist': {
      'circle': '○ 大圆圈',
      'disc': '● 小黑点',
      'square': '■ 小方块 ',
      'dash': '— 破折号',
      'dot': ' 。 小圆圈'
    },
    'paragraph': {
      'p': '段落',
      'h1': '一级标题',
      'h2': '二级标题',
      'h3': '三级标题',
      'h4': '四级标题',
      'h5': '五级标题',
      'h6': '六级标题'
    },
    'fontfamily': {
      'songti': '宋体',
      'kaiti': '楷体',
      'heiti': '黑体',
      'lishu': '隶书',
      'yahei': '微软雅黑',
      'andaleMono': 'andale mono',
      'arial': 'arial',
      'arialBlack': 'arial black',
      'comicSansMs': 'comic sans ms',
      'impact': 'impact',
      'timesNewRoman': 'times new roman'
    },
    'customstyle': {
      'tc': '标题居中',
      'tl': '标题居左',
      'im': '强调',
      'hi': '明显强调'
    },
    'autoupload': {
      'exceedSizeError': '文件大小超出' + constants.imageMaxSize,
      'exceedTypeError': '文件格式不允许',
      'jsonEncodeError': '服务器返回格式错误',
      'loading': "正在上传...",
      'loadError': "上传错误",
      'errorLoadConfig': '后端配置项没有正常加载，上传插件不能正常使用！'
    },
    'simpleupload': {
      'exceedSizeError': '文件大小超出' + constants.imageMaxSize,
      'exceedTypeError': '文件格式不允许',
      'jsonEncodeError': '服务器返回格式错误',
      'loading': "正在上传...",
      'loadError': "上传错误",
      'errorLoadConfig': '后端配置项没有正常加载，上传插件不能正常使用！'
    },
    'elementPathTip': "元素路径",
    'wordCountTip': "字数统计",
    'wordCountMsg': '当前已输入{#count}个字符, 您还可以输入{#leave}个字符。 ',
    'wordOverFlowMsg': '<span style="color:red;">字数超出最大允许值，服务器可能拒绝保存！</span>',
    'ok': "确认",
    'cancel': "取消",
    'closeDialog': "关闭对话框",
    'tableDrag': "表格拖动必须引入uiUtils.js文件！",
    'autofloatMsg': "工具栏浮动依赖编辑器UI，您首先需要引入UI文件!",
    'loadconfigError': '获取后台配置项请求出错，上传功能将不能正常使用！',
    'loadconfigFormatError': '后台配置项返回格式出错，上传功能将不能正常使用！',
    'loadconfigHttpError': '请求后台配置项http错误，上传功能将不能正常使用！',
    'snapScreen_plugin': {
      'browserMsg': "仅支持IE浏览器！",
      'callBackErrorMsg': "服务器返回数据有误，请检查配置项之后重试。",
      'uploadErrorMsg': "截图上传失败，请检查服务器端环境! "
    },
    'insertcode': {
      'as3': 'ActionScript 3',
      'bash': 'Bash/Shell',
      'cpp': 'C/C++',
      'css': 'CSS',
      'cf': 'ColdFusion',
      'c#': 'C#',
      'delphi': 'Delphi',
      'diff': 'Diff',
      'erlang': 'Erlang',
      'groovy': 'Groovy',
      'html': 'HTML',
      'java': 'Java',
      'jfx': 'JavaFX',
      'js': 'JavaScript',
      'pl': 'Perl',
      'php': 'PHP',
      'plain': 'Plain Text',
      'ps': 'PowerShell',
      'python': 'Python',
      'ruby': 'Ruby',
      'scala': 'Scala',
      'sql': 'SQL',
      'vb': 'Visual Basic',
      'xml': 'XML'
    },
    'confirmClear': "确定清空当前文档么？",
    'contextMenu': {
      'delete': "删除",
      'selectall': "全选",
      'deletecode': "删除代码",
      'cleardoc': "清空文档",
      'confirmclear': "确定清空当前文档么？",
      'unlink': "删除超链接",
      'paragraph': "段落格式",
      'edittable': "表格属性",
      'aligntd': "单元格对齐方式",
      'aligntable': '表格对齐方式',
      'tableleft': '左浮动',
      'tablecenter': '居中显示',
      'tableright': '右浮动',
      'edittd': "单元格属性",
      'setbordervisible': '设置表格边线可见',
      'justifyleft': '左对齐',
      'justifyright': '右对齐',
      'justifycenter': '居中对齐',
      'justifyjustify': '两端对齐',
      'table': "表格",
      'inserttable': '插入表格',
      'deletetable': "删除表格",
      'insertparagraphbefore': "前插入段落",
      'insertparagraphafter': '后插入段落',
      'deleterow': "删除当前行",
      'deletecol': "删除当前列",
      'insertrow': "前插入行",
      'insertcol': "左插入列",
      'insertrownext': '后插入行',
      'insertcolnext': '右插入列',
      'insertcaption': '插入表格名称',
      'deletecaption': '删除表格名称',
      'inserttitle': '插入表格标题行',
      'deletetitle': '删除表格标题行',
      'inserttitlecol': '插入表格标题列',
      'deletetitlecol': '删除表格标题列',
      'averageDiseRow': '平均分布各行',
      'averageDisCol': '平均分布各列',
      'mergeright': "向右合并",
      'mergeleft': "向左合并",
      'mergedown': "向下合并",
      'mergecells': "合并单元格",
      'splittocells': "完全拆分单元格",
      'splittocols': "拆分成列",
      'splittorows': "拆分成行",
      'tablesort': '表格排序',
      'enablesort': '设置表格可排序',
      'disablesort': '取消表格可排序',
      'reversecurrent': '逆序当前',
      'orderbyasc': '按ASCII字符升序',
      'reversebyasc': '按ASCII字符降序',
      'orderbynum': '按数值大小升序',
      'reversebynum': '按数值大小降序',
      'borderbk': '边框底纹',
      'setcolor': '表格隔行变色',
      'unsetcolor': '取消表格隔行变色',
      'setbackground': '选区背景隔行',
      'unsetbackground': '取消选区背景',
      'redandblue': '红蓝相间',
      'threecolorgradient': '三色渐变',
      'copy': "复制(Ctrl + c)",
      'copymsg': "浏览器不支持,请使用 'Ctrl + c'",
      'paste': "粘贴(Ctrl + v)",
      'pastemsg': "浏览器不支持,请使用 'Ctrl + v'"
    },
    'copymsg': "浏览器不支持,请使用 'Ctrl + c'",
    'pastemsg': "浏览器不支持,请使用 'Ctrl + v'",
    'anthorMsg': "链接",
    'clearColor': '清空颜色',
    'standardColor': '标准颜色',
    'themeColor': '主题颜色',
    'property': '属性',
    'default': '默认',
    'modify': '修改',
    'justifyleft': '左对齐',
    'justifyright': '右对齐',
    'justifycenter': '居中',
    'justify': '默认',
    'changeImage': '换图',
    'edit': '编辑',
    'radiusCircle': '圆形',
    'cancelRadius': '取消圆形',
    'ok': '确定',
    'recentlyColor': '最近使用颜色',
    'clear': '清除',
    'anchorMsg': '锚点',
    'delete': '删除',
    'clickToUpload': "点击上传",
    'unset': '尚未设置语言文件',
    't_row': '行',
    't_col': '列',
    'more': '更多',
    'pasteOpt': '粘贴选项',
    'pasteSourceFormat': "保留源格式",
    'tagFormat': '只保留标签',
    'pasteTextFormat': '只保留文本',
    'autoTypeSet': {
      'mergeLine': "合并空行",
      'delLine': "清除空行",
      'removeFormat': "清除格式",
      'indent': "首行缩进",
      'alignment': "对齐方式",
      'imageFloat': "图片浮动",
      'removeFontsize': "清除字号",
      'removeFontFamily': "清除字体",
      'removeHtml': "清除冗余HTML代码",
      'pasteFilter': "粘贴过滤",
      'run': "执行",
      'symbol': '符号转换',
      'bdc2sb': '全角转半角',
      'tobdc': '半角转全角'
    },
    'background': {
      'static': {
        'lang_background_normal': '背景设置',
        'lang_background_local': '我的图片',
        'lang_background_set': '选项',
        'lang_background_none': '无背景色',
        'lang_background_colored': '有背景色',
        'lang_background_color': '颜色设置',
        'lang_background_netimg': '网络图片',
        'lang_background_align': '对齐方式',
        'lang_background_position': '精确定位',
        'repeatType': {
          'options': [ "居中", "横向重复", "纵向重复", "平铺", "自定义" ]
        }
      },
      'noUploadImage': "当前未上传过任何图片！",
      'toggleSelect': "单击可切换选中状态\n原图尺寸: "
    },
    'insertimage': {
      'static': {
        'lang_tab_remote': "插入图片",
        'lang_tab_upload': "本地上传",
        'lang_tab_online': "我的图片",
        'lang_tab_search': "图片搜索",
        'lang_input_url': "地 址：",
        'lang_input_size': "大 小：",
        'lang_input_width': "宽度",
        'lang_input_height': "高度",
        'lang_input_border': "边 框：",
        'lang_input_vhspace': "边 距：",
        'lang_input_title': "描 述：",
        'lang_input_align': '图片浮动方式：',
        'lang_imgLoading': "　图片加载中……",
        'lang_start_upload': "开始上传",
        'lock': {
          'title': "锁定宽高比例"
        },
        'searchType': {
          'title': "图片类型",
          'options': [ "新闻", "壁纸", "表情", "头像" ]
        },
        'searchTxt': {
          'value': "请输入搜索关键词"
        },
        'searchBtn': {
          'value': "百度一下"
        },
        'searchReset': {
          'value': "清空搜索"
        },
        'noneAlign': {
          'title': '无浮动'
        },
        'leftAlign': {
          'title': '左浮动'
        },
        'rightAlign': {
          'title': '右浮动'
        },
        'centerAlign': {
          'title': '居中独占一行'
        }
      },
      'uploadSelectFile': '点击选择图片',
      'uploadAddFile': '继续添加',
      'uploadStart': '开始上传',
      'uploadPause': '暂停上传',
      'uploadContinue': '继续上传',
      'uploadRetry': '重试上传',
      'uploadDelete': '删除',
      'uploadTurnLeft': '向左旋转',
      'uploadTurnRight': '向右旋转',
      'uploadPreview': '预览中',
      'uploadNoPreview': '不能预览',
      'updateStatusReady': '选中_张图片，共_KB。',
      'updateStatusConfirm': '已成功上传_张照片，_张照片上传失败',
      'updateStatusFinish': '共_张（_KB），_张上传成功',
      'updateStatusError': '，_张上传失败。',
      'errorNotSupport': 'WebUploader 不支持您的浏览器！如果你使用的是IE浏览器，请尝试升级 flash 播放器。',
      'errorLoadConfig': '后端配置项没有正常加载，上传插件不能正常使用！',
      'errorExceedSize': '文件大小超出',
      'errorFileType': '文件格式不允许',
      'errorInterrupt': '文件传输中断',
      'errorUploadRetry': '上传失败，请重试',
      'errorHttp': 'http请求错误',
      'errorServerUpload': '服务器返回出错',
      'remoteLockError': "宽高不正确,不能所定比例",
      'numError': "请输入正确的长度或者宽度值！例如：123，400",
      'imageUrlError': "不允许的图片格式或者图片域！",
      'imageLoadError': "图片加载失败！请检查链接地址或网络状态！",
      'searchRemind': "请输入搜索关键词",
      'searchLoading': "图片加载中，请稍后……",
      'searchRetry': " :( ，抱歉，没有找到图片！请重试一次！"
    },
    'attachment': {
      'static': {
        'lang_tab_upload': '上传附件',
        'lang_tab_online': '在线附件',
        'lang_start_upload': "开始上传",
        'lang_drop_remind': "可以将文件拖到这里，单次最多可选100个文件"
      },
      'uploadSelectFile': '点击选择文件',
      'uploadAddFile': '继续添加',
      'uploadStart': '开始上传',
      'uploadPause': '暂停上传',
      'uploadContinue': '继续上传',
      'uploadRetry': '重试上传',
      'uploadDelete': '删除',
      'uploadTurnLeft': '向左旋转',
      'uploadTurnRight': '向右旋转',
      'uploadPreview': '预览中',
      'updateStatusReady': '选中_个文件，共_KB。',
      'updateStatusConfirm': '已成功上传_个文件，_个文件上传失败',
      'updateStatusFinish': '共_个（_KB），_个上传成功',
      'updateStatusError': '，_张上传失败。',
      'errorNotSupport': 'WebUploader 不支持您的浏览器！如果你使用的是IE浏览器，请尝试升级 flash 播放器。',
      'errorLoadConfig': '后端配置项没有正常加载，上传插件不能正常使用！',
      'errorExceedSize': '文件大小超出',
      'errorFileType': '文件格式不允许',
      'errorInterrupt': '文件传输中断',
      'errorUploadRetry': '上传失败，请重试',
      'errorHttp': 'http请求错误',
      'errorServerUpload': '服务器返回出错'
    },
    'insertvideo': {
      'static': {
        'lang_tab_insertV': "插入视频",
        'lang_tab_searchV': "搜索视频",
        'lang_tab_uploadV': "上传视频",
        'lang_video_url': "视频网址",
        'lang_video_size': "视频尺寸",
        'lang_videoW': "宽度",
        'lang_videoH': "高度",
        'lang_alignment': "对齐方式",
        'videoSearchTxt': {
          'value': "请输入搜索关键字！"
        },
        'videoType': {
          'options': [ "全部", "热门", "娱乐", "搞笑", "体育", "科技", "综艺" ]
        },
        'videoSearchBtn': {
          'value': "百度一下"
        },
        'videoSearchReset': {
          'value': "清空结果"
        },
        'lang_input_fileStatus': ' 当前未上传文件',
        'startUpload': {
          'style': "background:url(upload.png) no-repeat;"
        },
        'lang_upload_size': "视频尺寸",
        'lang_upload_width': "宽度",
        'lang_upload_height': "高度",
        'lang_upload_alignment': "对齐方式",
        'lang_format_advice': "建议使用mp4格式."
      },
      'numError': "请输入正确的数值，如123,400",
      'floatLeft': "左浮动",
      'floatRight': "右浮动",
      '"default"': "默认",
      'block': "独占一行",
      'urlError': "输入的视频地址有误，请检查后再试！",
      'loading': " &nbsp;视频加载中，请等待……",
      'clickToSelect': "点击选中",
      'goToSource': '访问源视频',
      'noVideo': " &nbsp; &nbsp;抱歉，找不到对应的视频，请重试！",
      'browseFiles': '浏览文件',
      'uploadSuccess': '上传成功!',
      'delSuccessFile': '从成功队列中移除',
      'delFailSaveFile': '移除保存失败文件',
      'statusPrompt': ' 个文件已上传！ ',
      'flashVersionError': '当前Flash版本过低，请更新FlashPlayer后重试！',
      'flashLoadingError': 'Flash加载失败!请检查路径或网络状态',
      'fileUploadReady': '等待上传……',
      'delUploadQueue': '从上传队列中移除',
      'limitPrompt1': '单次不能选择超过',
      'limitPrompt2': '个文件！请重新选择！',
      'delFailFile': '移除失败文件',
      'fileSizeLimit': '文件大小超出限制！',
      'emptyFile': '空文件无法上传！',
      'fileTypeError': '文件类型不允许！',
      'unknownError': '未知错误！',
      'fileUploading': '上传中，请等待……',
      'cancelUpload': '取消上传',
      'netError': '网络错误',
      'failUpload': '上传失败!',
      'serverIOError': '服务器IO错误！',
      'noAuthority': '无权限！',
      'fileNumLimit': '上传个数限制',
      'failCheck': '验证失败，本次上传被跳过！',
      'fileCanceling': '取消中，请等待……',
      'stopUploading': '上传已停止……',
      'uploadSelectFile': '点击选择文件',
      'uploadAddFile': '继续添加',
      'uploadStart': '开始上传',
      'uploadPause': '暂停上传',
      'uploadContinue': '继续上传',
      'uploadRetry': '重试上传',
      'uploadDelete': '删除',
      'uploadTurnLeft': '向左旋转',
      'uploadTurnRight': '向右旋转',
      'uploadPreview': '预览中',
      'updateStatusReady': '选中_个文件，共_KB。',
      'updateStatusConfirm': '成功上传_个，_个失败',
      'updateStatusFinish': '共_个(_KB)，_个成功上传',
      'updateStatusError': '，_张上传失败。',
      'errorNotSupport': 'WebUploader 不支持您的浏览器！如果你使用的是IE浏览器，请尝试升级 flash 播放器。',
      'errorLoadConfig': '后端配置项没有正常加载，上传插件不能正常使用！',
      'errorExceedSize': '文件大小超出',
      'errorFileType': '文件格式不允许',
      'errorInterrupt': '文件传输中断',
      'errorUploadRetry': '上传失败，请重试',
      'errorHttp': 'http请求错误',
      'errorServerUpload': '服务器返回出错'
    },
    'webapp': {
      'tip1': "本功能由百度APP提供，如看到此页面，请各位站长首先申请百度APPKey!",
      'tip2': "申请完成之后请至ueditor.config.js中配置获得的appkey! ",
      'applyFor': "点此申请",
      'anthorApi': "百度API"
    },
    'template': {
      'static': {
        'lang_template_bkcolor': '背景颜色',
        'lang_template_clear': '保留原有内容',
        'lang_template_select': '选择模板'
      },
      'blank': "空白文档",
      'blog': "博客文章",
      'resume': "个人简历",
      'richText': "图文混排",
      'sciPapers': "科技论文"
    },
    'scrawl': {
      'static': {
        'lang_input_previousStep': "上一步",
        'lang_input_nextsStep': "下一步",
        'lang_input_clear': '清空',
        'lang_input_addPic': '添加背景',
        'lang_input_ScalePic': '缩放背景',
        'lang_input_removePic': '删除背景',
        'J_imgTxt': {
          title: '添加背景图片'
        }
      },
      'noScarwl': "尚未作画，白纸一张~",
      'scrawlUpLoading': "涂鸦上传中,别急哦~",
      'continueBtn': "继续",
      'imageError': "糟糕，图片读取失败了！",
      'backgroundUploading': '背景图片上传中,别急哦~'
    },
    'music': {
      'static': {
        'lang_input_tips': "输入歌手/歌曲/专辑，搜索您感兴趣的音乐！",
        'J_searchBtn': {
          value: '搜索歌曲'
        }
      },
      'emptyTxt': '未搜索到相关音乐结果，请换一个关键词试试。',
      'chapter': '歌曲',
      'singer': '歌手',
      'special': '专辑',
      'listenTest': '试听'
    },
    'anchor': {
      'static': {
        'lang_input_anchorName': '锚点名字：'
      }
    },
    'charts': {
      'static': {
        'lang_data_source': '数据源：',
        'lang_chart_format': '图表格式：',
        'lang_data_align': '数据对齐方式',
        'lang_chart_align_same': '数据源与图表X轴Y轴一致',
        'lang_chart_align_reverse': '数据源与图表X轴Y轴相反',
        'lang_chart_title': '图表标题',
        'lang_chart_main_title': '主标题：',
        'lang_chart_sub_title': '子标题：',
        'lang_chart_x_title': 'X轴标题：',
        'lang_chart_y_title': 'Y轴标题：',
        'lang_chart_tip': '提示文字',
        'lang_cahrt_tip_prefix': '提示文字前缀：',
        'lang_cahrt_tip_description': '仅饼图有效， 当鼠标移动到饼图中相应的块上时，提示框内的文字的前缀',
        'lang_chart_data_unit': '数据单位',
        'lang_chart_data_unit_title': '单位：',
        'lang_chart_data_unit_description': '显示在每个数据点上的数据的单位， 比如： 温度的单位 ℃',
        'lang_chart_type': '图表类型：',
        'lang_prev_btn': '上一个',
        'lang_next_btn': '下一个'
      }
    },
    'emotion': {
      'static': {
        'lang_input_choice': '精选',
        'lang_input_Tuzki': '兔斯基',
        'lang_input_BOBO': 'BOBO',
        'lang_input_lvdouwa': '绿豆蛙',
        'lang_input_babyCat': 'baby猫',
        'lang_input_bubble': '泡泡',
        'lang_input_youa': '有啊',
        'lang_input_bigwe': '微知',
      }
    },
    'gmap': {
      'static': {
        'lang_input_address': '地址',
        'lang_input_search': '搜索',
        'address': {
          value: "北京"
        }
      },
      searchError: '无法定位到该地址!'
    },
    'help': {
      'static': {
        'lang_input_about': '关于UEditor',
        'lang_input_shortcuts': '快捷键',
        'lang_input_introduction': 'UEditor是由百度web前端研发部开发的所见即所得富文本web编辑器，具有轻量，可定制，注重用户体验等特点。开源基于BSD协议，允许自由使用和修改代码。',
        'lang_Txt_shortcuts': '快捷键',
        'lang_Txt_func': '功能',
        'lang_Txt_bold': '给选中字设置为加粗',
        'lang_Txt_copy': '复制选中内容',
        'lang_Txt_cut': '剪切选中内容',
        'lang_Txt_Paste': '粘贴',
        'lang_Txt_undo': '重新执行上次操作',
        'lang_Txt_redo': '撤销上一次操作',
        'lang_Txt_italic': '给选中字设置为斜体',
        'lang_Txt_underline': '给选中字加下划线',
        'lang_Txt_selectAll': '全部选中',
        'lang_Txt_visualEnter': '软回车',
        'lang_Txt_fullscreen': '全屏'
      }
    },
    'insertframe': {
      'static': {
        'lang_input_address': '地址：',
        'lang_input_width': '宽度：',
        'lang_input_height': '高度：',
        'lang_input_isScroll': '允许滚动条：',
        'lang_input_frameborder': '显示框架边框：',
        'lang_input_alignMode': '对齐方式：',
        'align': {
          title: "对齐方式",
          options: [ "默认", "左对齐", "右对齐", "居中" ]
        }
      },
      'enterAddress': '请输入地址!'
    },
    'link': {
      'static': {
        'lang_input_text': '文本内容：',
        'lang_input_url': '链接地址：',
        'lang_input_title': '标题：',
        'lang_input_target': '是否在新窗口打开：'
      },
      'validLink': '只支持选中一个链接时生效',
      'httpPrompt': '您输入的超链接中不包含http等协议名称，默认将为您添加http://前缀'
    },
    'map': {
      'static': {
        lang_city: "城市",
        lang_address: "地址",
        city: {
          value: "北京"
        },
        lang_search: "搜索",
        lang_dynamicmap: "插入动态地图"
      },
      cityMsg: "请选择城市",
      errorMsg: "抱歉，找不到该位置！"
    },
    'searchreplace': {
      'static': {
        lang_tab_search: "查找",
        lang_tab_replace: "替换",
        lang_search1: "查找",
        lang_search2: "查找",
        lang_replace: "替换",
        lang_searchReg: '支持正则表达式，添加前后斜杠标示为正则表达式，例如“/表达式/”',
        lang_searchReg1: '支持正则表达式，添加前后斜杠标示为正则表达式，例如“/表达式/”',
        lang_case_sensitive1: "区分大小写",
        lang_case_sensitive2: "区分大小写",
        nextFindBtn: {
          value: "下一个"
        },
        preFindBtn: {
          value: "上一个"
        },
        nextReplaceBtn: {
          value: "下一个"
        },
        preReplaceBtn: {
          value: "上一个"
        },
        repalceBtn: {
          value: "替换"
        },
        repalceAllBtn: {
          value: "全部替换"
        }
      },
      getEnd: "已经搜索到文章末尾！",
      getStart: "已经搜索到文章头部",
      countMsg: "总共替换了{#count}处！"
    },
    'snapscreen': {
      'static': {
        lang_showMsg: "截图功能需要首先安装UEditor截图插件！ ",
        lang_download: "点此下载",
        lang_step1: "第一步，下载UEditor截图插件并运行安装。",
        lang_step2: "第二步，插件安装完成后即可使用，如不生效，请重启浏览器后再试！"
      }
    },
    'spechars': {
      'static': {},
      tsfh: "特殊字符",
      lmsz: "罗马字符",
      szfh: "数学字符",
      rwfh: "日文字符",
      xlzm: "希腊字母",
      ewzm: "俄文字符",
      pyzm: "拼音字母",
      yyyb: "英语音标",
      zyzf: "其他"
    },
    'edittable': {
      'static': {
        'lang_tableStyle': '表格样式',
        'lang_insertCaption': '添加表格名称行',
        'lang_insertTitle': '添加表格标题行',
        'lang_insertTitleCol': '添加表格标题列',
        'lang_orderbycontent': "使表格内容可排序",
        'lang_tableSize': '自动调整表格尺寸',
        'lang_autoSizeContent': '按表格文字自适应',
        'lang_autoSizePage': '按页面宽度自适应',
        'lang_example': '示例',
        'lang_borderStyle': '表格边框',
        'lang_color': '颜色:'
      },
      captionName: '表格名称',
      titleName: '标题',
      cellsName: '内容',
      errorMsg: '有合并单元格，不可排序'
    },
    'edittip': {
      'static': {
        lang_delRow: '删除整行',
        lang_delCol: '删除整列'
      }
    },
    'edittd': {
      'static': {
        lang_tdBkColor: '背景颜色:'
      }
    },
    'formula': {
      'static': {}
    },
    'wordimage': {
      'static': {
        lang_resave: "转存步骤",
        uploadBtn: {
          src: "upload.png",
          alt: "上传"
        },
        clipboard: {
          style: "background: url(copy.png) -153px -1px no-repeat;"
        },
        lang_step: "1、点击顶部复制按钮，将地址复制到剪贴板；2、点击添加照片按钮，在弹出的对话框中使用Ctrl+V粘贴地址；3、点击打开后选择图片上传流程。"
      },
      'fileType': "图片",
      'flashError': "FLASH初始化失败，请检查FLASH插件是否正确安装！",
      'netError': "网络连接错误，请重试！",
      'copySuccess': "图片地址已经复制！",
      'flashI18n': {}
    },
    'autosave': {
      'saving': '保存中...',
      'success': '本地保存成功'
    },
    'synonyms': {
      'static': {
        'synonyms': '近义词：',
        'prev': '上一个',
        'next': '下一个',
        'replace': '替换',
        'replaceall': '替换全部',
        'query': '查询',
        'underlineword': '划词',
        'underline': '划词',
        'findtxt1': {
          placeholder: '请输入词语'
        }
      },
      querying: '查询中...',
      getEnd: "已经搜索到文章末尾！",
      getStart: "已经搜索到文章头部",
      countMsg: "总共替换了{#count}处！",
      noData: '<span class="gray js_remove">未找到合适的近义词</span>',
      nodataReplace: "没有可替换的内容！"
    }
  };

  ( function( factory ) {
    /*if (typeof define === 'function' && define.amd) {
    	define(['jquery'], factory);
    } else if (typeof exports === 'object') {
    	factory(require('jquery'));
    } else {
    }*/
    factory( jQuery );
  }( function( $ ) {
    var pluses = /\+/g;

    function encode( s ) {
      return config.raw ? s : encodeURIComponent( s );
    }

    function decode( s ) {
      return config.raw ? s : decodeURIComponent( s );
    }

    function stringifyCookieValue( value ) {
      return encode( config.json ? JSON.stringify( value ) : String( value ) );
    }

    function parseCookieValue( s ) {
      if ( s.indexOf( '"' ) === 0 ) {
        s = s.slice( 1, -1 ).replace( /\\"/g, '"' ).replace( /\\\\/g, '\\' );
      }
      try {
        s = decodeURIComponent( s.replace( pluses, ' ' ) );
        return config.json ? JSON.parse( s ) : s;
      } catch ( e ) {}
    }

    function read( s, converter ) {
      var value = config.raw ? s : parseCookieValue( s );
      return $.isFunction( converter ) ? converter( value ) : value;
    }
    var config = $.cookie = function( key, value, options ) {
      if ( value !== undefined && !$.isFunction( value ) ) {
        options = $.extend( {}, config.defaults, options );
        if ( typeof options.expires === 'number' ) {
          var days = options.expires,
            t = options.expires = new Date();
          t.setTime( +t + days * 864e+5 );
        }
        return ( document.cookie = [ encode( key ), '=', stringifyCookieValue( value ), options.expires ? '; expires=' + options.expires.toUTCString() : '', options.path ? '; path=' + options.path : '', options.domain ? '; domain=' + options.domain : '', options.secure ? '; secure' : '' ].join( '' ) );
      }
      var result = key ? undefined : {};
      var cookies = document.cookie ? document.cookie.split( '; ' ) : [];
      for ( var i = 0, l = cookies.length; i < l; i++ ) {
        var parts = cookies[ i ].split( '=' );
        var name = decode( parts.shift() );
        var cookie = parts.join( '=' );
        if ( key && key === name ) {
          result = read( cookie, value );
          break;
        }
        if ( !key && ( cookie = read( cookie ) ) !== undefined ) {
          result[ name ] = cookie;
        }
      }
      return result;
    };
    config.defaults = {};
    $.removeCookie = function( key, options ) {
      if ( $.cookie( key ) === undefined ) {
        return false;
      }
      $.cookie( key, '', $.extend( {}, options, {
        expires: -1
      } ) );
      return !$.cookie( key );
    };
  } ) );;
  /*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh)
   * Licensed under the MIT License (LICENSE.txt).
   *
   * Version: 3.1.12
   *
   * Requires: jQuery 1.2.2+
   */
  ! function( a ) {
    /*"function" == typeof define && define.amd ? define(["jquery"], a) : "object" == typeof exports ? module.exports = a : */
    a( jQuery )
  }( function( a ) {
    function b( b ) {
      var g = b || window.event,
        h = i.call( arguments, 1 ),
        j = 0,
        l = 0,
        m = 0,
        n = 0,
        o = 0,
        p = 0;
      if ( b = a.event.fix( g ), b.type = "mousewheel", "detail" in g && ( m = -1 * g.detail ), "wheelDelta" in g && ( m = g.wheelDelta ), "wheelDeltaY" in g && ( m = g.wheelDeltaY ), "wheelDeltaX" in g && ( l = -1 * g.wheelDeltaX ), "axis" in g && g.axis === g.HORIZONTAL_AXIS && ( l = -1 * m, m = 0 ), j = 0 === m ? l : m, "deltaY" in g && ( m = -1 * g.deltaY, j = m ), "deltaX" in g && ( l = g.deltaX, 0 === m && ( j = -1 * l ) ), 0 !== m || 0 !== l ) {
        if ( 1 === g.deltaMode ) {
          var q = a.data( this, "mousewheel-line-height" );
          j *= q, m *= q, l *= q
        } else if ( 2 === g.deltaMode ) {
          var r = a.data( this, "mousewheel-page-height" );
          j *= r, m *= r, l *= r
        }
        if ( n = Math.max( Math.abs( m ), Math.abs( l ) ), ( !f || f > n ) && ( f = n, d( g, n ) && ( f /= 40 ) ), d( g, n ) && ( j /= 40, l /= 40, m /= 40 ), j = Math[ j >= 1 ? "floor" : "ceil" ]( j / f ), l = Math[ l >= 1 ? "floor" : "ceil" ]( l / f ), m = Math[ m >= 1 ? "floor" : "ceil" ]( m / f ), k.settings.normalizeOffset && this.getBoundingClientRect ) {
          var s = this.getBoundingClientRect();
          o = b.clientX - s.left, p = b.clientY - s.top
        }
        return b.deltaX = l, b.deltaY = m, b.deltaFactor = f, b.offsetX = o, b.offsetY = p, b.deltaMode = 0, h.unshift( b, j, l, m ), e && clearTimeout( e ), e = setTimeout( c, 200 ), ( a.event.dispatch || a.event.handle ).apply( this, h )
      }
    }

    function c() {
      f = null
    }

    function d( a, b ) {
      return k.settings.adjustOldDeltas && "mousewheel" === a.type && b % 120 === 0
    }
    var e, f, g = [ "wheel", "mousewheel", "DOMMouseScroll", "MozMousePixelScroll" ],
      h = "onwheel" in document || document.documentMode >= 9 ? [ "wheel" ] : [ "mousewheel", "DomMouseScroll", "MozMousePixelScroll" ],
      i = Array.prototype.slice;
    if ( a.event.fixHooks )
      for ( var j = g.length; j; ) a.event.fixHooks[ g[ --j ] ] = a.event.mouseHooks;
    var k = a.event.special.mousewheel = {
      version: "3.1.12",
      setup: function() {
        if ( this.addEventListener )
          for ( var c = h.length; c; ) this.addEventListener( h[ --c ], b, !1 );
        else this.onmousewheel = b;
        a.data( this, "mousewheel-line-height", k.getLineHeight( this ) ), a.data( this, "mousewheel-page-height", k.getPageHeight( this ) )
      },
      teardown: function() {
        if ( this.removeEventListener )
          for ( var c = h.length; c; ) this.removeEventListener( h[ --c ], b, !1 );
        else this.onmousewheel = null;
        a.removeData( this, "mousewheel-line-height" ), a.removeData( this, "mousewheel-page-height" )
      },
      getLineHeight: function( b ) {
        var c = a( b ),
          d = c[ "offsetParent" in a.fn ? "offsetParent" : "parent" ]();
        return d.length || ( d = a( "body" ) ), parseInt( d.css( "fontSize" ), 10 ) || parseInt( c.css( "fontSize" ), 10 ) || 16
      },
      getPageHeight: function( b ) {
        return a( b ).height()
      },
      settings: {
        adjustOldDeltas: !0,
        normalizeOffset: !0
      }
    };
    a.fn.extend( {
      mousewheel: function( a ) {
        return a ? this.bind( "mousewheel", a ) : this.trigger( "mousewheel" )
      },
      unmousewheel: function( a ) {
        return this.unbind( "mousewheel", a )
      }
    } )
  } );;

  ! function() {
    function tinycolor( color, opts ) {
      if ( color = color ? color : "", opts = opts || {}, color instanceof tinycolor ) return color;
      if ( !( this instanceof tinycolor ) ) return new tinycolor( color, opts );
      var rgb = inputToRGB( color );
      this._originalInput = color, this._r = rgb.r, this._g = rgb.g, this._b = rgb.b, this._a = rgb.a, this._roundA = mathRound( 100 * this._a ) / 100, this._format = opts.format || rgb.format, this._gradientType = opts.gradientType, this._r < 1 && ( this._r = mathRound( this._r ) ), this._g < 1 && ( this._g = mathRound( this._g ) ), this._b < 1 && ( this._b = mathRound( this._b ) ), this._ok = rgb.ok, this._tc_id = tinyCounter++
    }

    function inputToRGB( color ) {
      var rgb = {
          r: 0,
          g: 0,
          b: 0
        },
        a = 1,
        ok = !1,
        format = !1;
      return "string" == typeof color && ( color = stringInputToObject( color ) ), "object" == typeof color && ( color.hasOwnProperty( "r" ) && color.hasOwnProperty( "g" ) && color.hasOwnProperty( "b" ) ? ( rgb = rgbToRgb( color.r, color.g, color.b ), ok = !0, format = "%" === String( color.r ).substr( -1 ) ? "prgb" : "rgb" ) : color.hasOwnProperty( "h" ) && color.hasOwnProperty( "s" ) && color.hasOwnProperty( "v" ) ? ( color.s = convertToPercentage( color.s ), color.v = convertToPercentage( color.v ), rgb = hsvToRgb( color.h, color.s, color.v ), ok = !0, format = "hsv" ) : color.hasOwnProperty( "h" ) && color.hasOwnProperty( "s" ) && color.hasOwnProperty( "l" ) && ( color.s = convertToPercentage( color.s ), color.l = convertToPercentage( color.l ), rgb = hslToRgb( color.h, color.s, color.l ), ok = !0, format = "hsl" ), color.hasOwnProperty( "a" ) && ( a = color.a ) ), a = boundAlpha( a ), {
        ok: ok,
        format: color.format || format,
        r: mathMin( 255, mathMax( rgb.r, 0 ) ),
        g: mathMin( 255, mathMax( rgb.g, 0 ) ),
        b: mathMin( 255, mathMax( rgb.b, 0 ) ),
        a: a
      }
    }

    function rgbToRgb( r, g, b ) {
      return {
        r: 255 * bound01( r, 255 ),
        g: 255 * bound01( g, 255 ),
        b: 255 * bound01( b, 255 )
      }
    }

    function rgbToHsl( r, g, b ) {
      r = bound01( r, 255 ), g = bound01( g, 255 ), b = bound01( b, 255 );
      var h, s, max = mathMax( r, g, b ),
        min = mathMin( r, g, b ),
        l = ( max + min ) / 2;
      if ( max == min ) h = s = 0;
      else {
        var d = max - min;
        switch ( s = l > .5 ? d / ( 2 - max - min ) : d / ( max + min ), max ) {
          case r:
            h = ( g - b ) / d + ( b > g ? 6 : 0 );
            break;
          case g:
            h = ( b - r ) / d + 2;
            break;
          case b:
            h = ( r - g ) / d + 4
        }
        h /= 6
      }
      return {
        h: h,
        s: s,
        l: l
      }
    }

    function hslToRgb( h, s, l ) {
      function hue2rgb( p, q, t ) {
        return 0 > t && ( t += 1 ), t > 1 && ( t -= 1 ), 1 / 6 > t ? p + 6 * ( q - p ) * t : .5 > t ? q : 2 / 3 > t ? p + 6 * ( q - p ) * ( 2 / 3 - t ) : p
      }
      var r, g, b;
      if ( h = bound01( h, 360 ), s = bound01( s, 100 ), l = bound01( l, 100 ), 0 === s ) r = g = b = l;
      else {
        var q = .5 > l ? l * ( 1 + s ) : l + s - l * s,
          p = 2 * l - q;
        r = hue2rgb( p, q, h + 1 / 3 ), g = hue2rgb( p, q, h ), b = hue2rgb( p, q, h - 1 / 3 )
      }
      return {
        r: 255 * r,
        g: 255 * g,
        b: 255 * b
      }
    }

    function rgbToHsv( r, g, b ) {
      r = bound01( r, 255 ), g = bound01( g, 255 ), b = bound01( b, 255 );
      var h, s, max = mathMax( r, g, b ),
        min = mathMin( r, g, b ),
        v = max,
        d = max - min;
      if ( s = 0 === max ? 0 : d / max, max == min ) h = 0;
      else {
        switch ( max ) {
          case r:
            h = ( g - b ) / d + ( b > g ? 6 : 0 );
            break;
          case g:
            h = ( b - r ) / d + 2;
            break;
          case b:
            h = ( r - g ) / d + 4
        }
        h /= 6
      }
      return {
        h: h,
        s: s,
        v: v
      }
    }

    function hsvToRgb( h, s, v ) {
      h = 6 * bound01( h, 360 ), s = bound01( s, 100 ), v = bound01( v, 100 );
      var i = math.floor( h ),
        f = h - i,
        p = v * ( 1 - s ),
        q = v * ( 1 - f * s ),
        t = v * ( 1 - ( 1 - f ) * s ),
        mod = i % 6,
        r = [ v, q, p, p, t, v ][ mod ],
        g = [ t, v, v, q, p, p ][ mod ],
        b = [ p, p, t, v, v, q ][ mod ];
      return {
        r: 255 * r,
        g: 255 * g,
        b: 255 * b
      }
    }

    function rgbToHex( r, g, b, allow3Char ) {
      var hex = [ pad2( mathRound( r ).toString( 16 ) ), pad2( mathRound( g ).toString( 16 ) ), pad2( mathRound( b ).toString( 16 ) ) ];
      return allow3Char && hex[ 0 ].charAt( 0 ) == hex[ 0 ].charAt( 1 ) && hex[ 1 ].charAt( 0 ) == hex[ 1 ].charAt( 1 ) && hex[ 2 ].charAt( 0 ) == hex[ 2 ].charAt( 1 ) ? hex[ 0 ].charAt( 0 ) + hex[ 1 ].charAt( 0 ) + hex[ 2 ].charAt( 0 ) : hex.join( "" )
    }

    function rgbaToHex( r, g, b, a ) {
      var hex = [ pad2( convertDecimalToHex( a ) ), pad2( mathRound( r ).toString( 16 ) ), pad2( mathRound( g ).toString( 16 ) ), pad2( mathRound( b ).toString( 16 ) ) ];
      return hex.join( "" )
    }

    function desaturate( color, amount ) {
      amount = 0 === amount ? 0 : amount || 10;
      var hsl = tinycolor( color ).toHsl();
      return hsl.s -= amount / 100, hsl.s = clamp01( hsl.s ), tinycolor( hsl )
    }

    function saturate( color, amount ) {
      amount = 0 === amount ? 0 : amount || 10;
      var hsl = tinycolor( color ).toHsl();
      return hsl.s += amount / 100, hsl.s = clamp01( hsl.s ), tinycolor( hsl )
    }

    function greyscale( color ) {
      return tinycolor( color ).desaturate( 100 )
    }

    function lighten( color, amount ) {
      amount = 0 === amount ? 0 : amount || 10;
      var hsl = tinycolor( color ).toHsl();
      return hsl.l += amount / 100, hsl.l = clamp01( hsl.l ), tinycolor( hsl )
    }

    function brighten( color, amount ) {
      amount = 0 === amount ? 0 : amount || 10;
      var rgb = tinycolor( color ).toRgb();
      return rgb.r = mathMax( 0, mathMin( 255, rgb.r - mathRound( 255 * -( amount / 100 ) ) ) ), rgb.g = mathMax( 0, mathMin( 255, rgb.g - mathRound( 255 * -( amount / 100 ) ) ) ), rgb.b = mathMax( 0, mathMin( 255, rgb.b - mathRound( 255 * -( amount / 100 ) ) ) ), tinycolor( rgb )
    }

    function darken( color, amount ) {
      amount = 0 === amount ? 0 : amount || 10;
      var hsl = tinycolor( color ).toHsl();
      return hsl.l -= amount / 100, hsl.l = clamp01( hsl.l ), tinycolor( hsl )
    }

    function spin( color, amount ) {
      var hsl = tinycolor( color ).toHsl(),
        hue = ( mathRound( hsl.h ) + amount ) % 360;
      return hsl.h = 0 > hue ? 360 + hue : hue, tinycolor( hsl )
    }

    function complement( color ) {
      var hsl = tinycolor( color ).toHsl();
      return hsl.h = ( hsl.h + 180 ) % 360, tinycolor( hsl )
    }

    function triad( color ) {
      var hsl = tinycolor( color ).toHsl(),
        h = hsl.h;
      return [ tinycolor( color ), tinycolor( {
        h: ( h + 120 ) % 360,
        s: hsl.s,
        l: hsl.l
      } ), tinycolor( {
        h: ( h + 240 ) % 360,
        s: hsl.s,
        l: hsl.l
      } ) ]
    }

    function tetrad( color ) {
      var hsl = tinycolor( color ).toHsl(),
        h = hsl.h;
      return [ tinycolor( color ), tinycolor( {
        h: ( h + 90 ) % 360,
        s: hsl.s,
        l: hsl.l
      } ), tinycolor( {
        h: ( h + 180 ) % 360,
        s: hsl.s,
        l: hsl.l
      } ), tinycolor( {
        h: ( h + 270 ) % 360,
        s: hsl.s,
        l: hsl.l
      } ) ]
    }

    function splitcomplement( color ) {
      var hsl = tinycolor( color ).toHsl(),
        h = hsl.h;
      return [ tinycolor( color ), tinycolor( {
        h: ( h + 72 ) % 360,
        s: hsl.s,
        l: hsl.l
      } ), tinycolor( {
        h: ( h + 216 ) % 360,
        s: hsl.s,
        l: hsl.l
      } ) ]
    }

    function analogous( color, results, slices ) {
      results = results || 6, slices = slices || 30;
      var hsl = tinycolor( color ).toHsl(),
        part = 360 / slices,
        ret = [ tinycolor( color ) ];
      for ( hsl.h = ( hsl.h - ( part * results >> 1 ) + 720 ) % 360; --results; ) hsl.h = ( hsl.h + part ) % 360, ret.push( tinycolor( hsl ) );
      return ret
    }

    function monochromatic( color, results ) {
      results = results || 6;
      for ( var hsv = tinycolor( color ).toHsv(), h = hsv.h, s = hsv.s, v = hsv.v, ret = [], modification = 1 / results; results--; ) ret.push( tinycolor( {
        h: h,
        s: s,
        v: v
      } ) ), v = ( v + modification ) % 1;
      return ret
    }

    function flip( o ) {
      var flipped = {};
      for ( var i in o ) o.hasOwnProperty( i ) && ( flipped[ o[ i ] ] = i );
      return flipped
    }

    function boundAlpha( a ) {
      return a = parseFloat( a ), ( isNaN( a ) || 0 > a || a > 1 ) && ( a = 1 ), a
    }

    function bound01( n, max ) {
      isOnePointZero( n ) && ( n = "100%" );
      var processPercent = isPercentage( n );
      return n = mathMin( max, mathMax( 0, parseFloat( n ) ) ), processPercent && ( n = parseInt( n * max, 10 ) / 100 ), math.abs( n - max ) < 1e-6 ? 1 : n % max / parseFloat( max )
    }

    function clamp01( val ) {
      return mathMin( 1, mathMax( 0, val ) )
    }

    function parseIntFromHex( val ) {
      return parseInt( val, 16 )
    }

    function isOnePointZero( n ) {
      return "string" == typeof n && -1 != n.indexOf( "." ) && 1 === parseFloat( n )
    }

    function isPercentage( n ) {
      return "string" == typeof n && -1 != n.indexOf( "%" )
    }

    function pad2( c ) {
      return 1 == c.length ? "0" + c : "" + c
    }

    function convertToPercentage( n ) {
      return 1 >= n && ( n = 100 * n + "%" ), n
    }

    function convertDecimalToHex( d ) {
      return Math.round( 255 * parseFloat( d ) ).toString( 16 )
    }

    function convertHexToDecimal( h ) {
      return parseIntFromHex( h ) / 255
    }

    function stringInputToObject( color ) {
      color = color.replace( trimLeft, "" ).replace( trimRight, "" ).toLowerCase();
      var named = !1;
      if ( names[ color ] ) color = names[ color ], named = !0;
      else if ( "transparent" == color ) return {
        r: 0,
        g: 0,
        b: 0,
        a: 0,
        format: "name"
      };
      var match;
      return ( match = matchers.rgb.exec( color ) ) ? {
        r: match[ 1 ],
        g: match[ 2 ],
        b: match[ 3 ]
      } : ( match = matchers.rgba.exec( color ) ) ? {
        r: match[ 1 ],
        g: match[ 2 ],
        b: match[ 3 ],
        a: match[ 4 ]
      } : ( match = matchers.hsl.exec( color ) ) ? {
        h: match[ 1 ],
        s: match[ 2 ],
        l: match[ 3 ]
      } : ( match = matchers.hsla.exec( color ) ) ? {
        h: match[ 1 ],
        s: match[ 2 ],
        l: match[ 3 ],
        a: match[ 4 ]
      } : ( match = matchers.hsv.exec( color ) ) ? {
        h: match[ 1 ],
        s: match[ 2 ],
        v: match[ 3 ]
      } : ( match = matchers.hsva.exec( color ) ) ? {
        h: match[ 1 ],
        s: match[ 2 ],
        v: match[ 3 ],
        a: match[ 4 ]
      } : ( match = matchers.hex8.exec( color ) ) ? {
        a: convertHexToDecimal( match[ 1 ] ),
        r: parseIntFromHex( match[ 2 ] ),
        g: parseIntFromHex( match[ 3 ] ),
        b: parseIntFromHex( match[ 4 ] ),
        format: named ? "name" : "hex8"
      } : ( match = matchers.hex6.exec( color ) ) ? {
        r: parseIntFromHex( match[ 1 ] ),
        g: parseIntFromHex( match[ 2 ] ),
        b: parseIntFromHex( match[ 3 ] ),
        format: named ? "name" : "hex"
      } : ( match = matchers.hex3.exec( color ) ) ? {
        r: parseIntFromHex( match[ 1 ] + "" + match[ 1 ] ),
        g: parseIntFromHex( match[ 2 ] + "" + match[ 2 ] ),
        b: parseIntFromHex( match[ 3 ] + "" + match[ 3 ] ),
        format: named ? "name" : "hex"
      } : !1
    }

    function validateWCAG2Parms( parms ) {
      var level, size;
      return parms = parms || {
        level: "AA",
        size: "small"
      }, level = ( parms.level || "AA" ).toUpperCase(), size = ( parms.size || "small" ).toLowerCase(), "AA" !== level && "AAA" !== level && ( level = "AA" ), "small" !== size && "large" !== size && ( size = "small" ), {
        level: level,
        size: size
      }
    }
    var trimLeft = /^\s+/,
      trimRight = /\s+$/,
      tinyCounter = 0,
      math = Math,
      mathRound = math.round,
      mathMin = math.min,
      mathMax = math.max,
      mathRandom = math.random;
    tinycolor.prototype = {
      isDark: function() {
        return this.getBrightness() < 128
      },
      isLight: function() {
        return !this.isDark()
      },
      isValid: function() {
        return this._ok
      },
      getOriginalInput: function() {
        return this._originalInput
      },
      getFormat: function() {
        return this._format
      },
      getAlpha: function() {
        return this._a
      },
      getBrightness: function() {
        var rgb = this.toRgb();
        return ( 299 * rgb.r + 587 * rgb.g + 114 * rgb.b ) / 1e3
      },
      getLuminance: function() {
        var RsRGB, GsRGB, BsRGB, R, G, B, rgb = this.toRgb();
        return RsRGB = rgb.r / 255, GsRGB = rgb.g / 255, BsRGB = rgb.b / 255, R = .03928 >= RsRGB ? RsRGB / 12.92 : Math.pow( ( RsRGB + .055 ) / 1.055, 2.4 ), G = .03928 >= GsRGB ? GsRGB / 12.92 : Math.pow( ( GsRGB + .055 ) / 1.055, 2.4 ), B = .03928 >= BsRGB ? BsRGB / 12.92 : Math.pow( ( BsRGB + .055 ) / 1.055, 2.4 ), .2126 * R + .7152 * G + .0722 * B
      },
      setAlpha: function( value ) {
        return this._a = boundAlpha( value ), this._roundA = mathRound( 100 * this._a ) / 100, this
      },
      toHsv: function() {
        var hsv = rgbToHsv( this._r, this._g, this._b );
        return {
          h: 360 * hsv.h,
          s: hsv.s,
          v: hsv.v,
          a: this._a
        }
      },
      toHsvString: function() {
        var hsv = rgbToHsv( this._r, this._g, this._b ),
          h = mathRound( 360 * hsv.h ),
          s = mathRound( 100 * hsv.s ),
          v = mathRound( 100 * hsv.v );
        return 1 == this._a ? "hsv(" + h + ", " + s + "%, " + v + "%)" : "hsva(" + h + ", " + s + "%, " + v + "%, " + this._roundA + ")"
      },
      toHsl: function() {
        var hsl = rgbToHsl( this._r, this._g, this._b );
        return {
          h: 360 * hsl.h,
          s: hsl.s,
          l: hsl.l,
          a: this._a
        }
      },
      toHslString: function() {
        var hsl = rgbToHsl( this._r, this._g, this._b ),
          h = mathRound( 360 * hsl.h ),
          s = mathRound( 100 * hsl.s ),
          l = mathRound( 100 * hsl.l );
        return 1 == this._a ? "hsl(" + h + ", " + s + "%, " + l + "%)" : "hsla(" + h + ", " + s + "%, " + l + "%, " + this._roundA + ")"
      },
      toHex: function( allow3Char ) {
        return rgbToHex( this._r, this._g, this._b, allow3Char )
      },
      toHexString: function( allow3Char ) {
        return "#" + this.toHex( allow3Char )
      },
      toHex8: function() {
        return rgbaToHex( this._r, this._g, this._b, this._a )
      },
      toHex8String: function() {
        return "#" + this.toHex8()
      },
      toRgb: function() {
        return {
          r: mathRound( this._r ),
          g: mathRound( this._g ),
          b: mathRound( this._b ),
          a: this._a
        }
      },
      toRgbString: function() {
        return 1 == this._a ? "rgb(" + mathRound( this._r ) + ", " + mathRound( this._g ) + ", " + mathRound( this._b ) + ")" : "rgba(" + mathRound( this._r ) + ", " + mathRound( this._g ) + ", " + mathRound( this._b ) + ", " + this._roundA + ")"
      },
      toPercentageRgb: function() {
        return {
          r: mathRound( 100 * bound01( this._r, 255 ) ) + "%",
          g: mathRound( 100 * bound01( this._g, 255 ) ) + "%",
          b: mathRound( 100 * bound01( this._b, 255 ) ) + "%",
          a: this._a
        }
      },
      toPercentageRgbString: function() {
        return 1 == this._a ? "rgb(" + mathRound( 100 * bound01( this._r, 255 ) ) + "%, " + mathRound( 100 * bound01( this._g, 255 ) ) + "%, " + mathRound( 100 * bound01( this._b, 255 ) ) + "%)" : "rgba(" + mathRound( 100 * bound01( this._r, 255 ) ) + "%, " + mathRound( 100 * bound01( this._g, 255 ) ) + "%, " + mathRound( 100 * bound01( this._b, 255 ) ) + "%, " + this._roundA + ")"
      },
      toName: function() {
        return 0 === this._a ? "transparent" : this._a < 1 ? !1 : hexNames[ rgbToHex( this._r, this._g, this._b, !0 ) ] || !1
      },
      toFilter: function( secondColor ) {
        var hex8String = "#" + rgbaToHex( this._r, this._g, this._b, this._a ),
          secondHex8String = hex8String,
          gradientType = this._gradientType ? "GradientType = 1, " : "";
        if ( secondColor ) {
          var s = tinycolor( secondColor );
          secondHex8String = s.toHex8String()
        }
        return "progid:DXImageTransform.Microsoft.gradient(" + gradientType + "startColorstr=" + hex8String + ",endColorstr=" + secondHex8String + ")"
      },
      toString: function( format ) {
        var formatSet = !!format;
        format = format || this._format;
        var formattedString = !1,
          hasAlpha = this._a < 1 && this._a >= 0,
          needsAlphaFormat = !formatSet && hasAlpha && ( "hex" === format || "hex6" === format || "hex3" === format || "name" === format );
        return needsAlphaFormat ? "name" === format && 0 === this._a ? this.toName() : this.toRgbString() : ( "rgb" === format && ( formattedString = this.toRgbString() ), "prgb" === format && ( formattedString = this.toPercentageRgbString() ), ( "hex" === format || "hex6" === format ) && ( formattedString = this.toHexString() ), "hex3" === format && ( formattedString = this.toHexString( !0 ) ), "hex8" === format && ( formattedString = this.toHex8String() ), "name" === format && ( formattedString = this.toName() ), "hsl" === format && ( formattedString = this.toHslString() ), "hsv" === format && ( formattedString = this.toHsvString() ), formattedString || this.toHexString() )
      },
      clone: function() {
        return tinycolor( this.toString() )
      },
      _applyModification: function( fn, args ) {
        var color = fn.apply( null, [ this ].concat( [].slice.call( args ) ) );
        return this._r = color._r, this._g = color._g, this._b = color._b, this.setAlpha( color._a ), this
      },
      lighten: function() {
        return this._applyModification( lighten, arguments )
      },
      brighten: function() {
        return this._applyModification( brighten, arguments )
      },
      darken: function() {
        return this._applyModification( darken, arguments )
      },
      desaturate: function() {
        return this._applyModification( desaturate, arguments )
      },
      saturate: function() {
        return this._applyModification( saturate, arguments )
      },
      greyscale: function() {
        return this._applyModification( greyscale, arguments )
      },
      spin: function() {
        return this._applyModification( spin, arguments )
      },
      _applyCombination: function( fn, args ) {
        return fn.apply( null, [ this ].concat( [].slice.call( args ) ) )
      },
      analogous: function() {
        return this._applyCombination( analogous, arguments )
      },
      complement: function() {
        return this._applyCombination( complement, arguments )
      },
      monochromatic: function() {
        return this._applyCombination( monochromatic, arguments )
      },
      splitcomplement: function() {
        return this._applyCombination( splitcomplement, arguments )
      },
      triad: function() {
        return this._applyCombination( triad, arguments )
      },
      tetrad: function() {
        return this._applyCombination( tetrad, arguments )
      }
    }, tinycolor.fromRatio = function( color, opts ) {
      if ( "object" == typeof color ) {
        var newColor = {};
        for ( var i in color ) color.hasOwnProperty( i ) && ( newColor[ i ] = "a" === i ? color[ i ] : convertToPercentage( color[ i ] ) );
        color = newColor
      }
      return tinycolor( color, opts )
    }, tinycolor.equals = function( color1, color2 ) {
      return color1 && color2 ? tinycolor( color1 ).toRgbString() == tinycolor( color2 ).toRgbString() : !1
    }, tinycolor.random = function() {
      return tinycolor.fromRatio( {
        r: mathRandom(),
        g: mathRandom(),
        b: mathRandom()
      } )
    }, tinycolor.mix = function( color1, color2, amount ) {
      amount = 0 === amount ? 0 : amount || 50;
      var w1, rgb1 = tinycolor( color1 ).toRgb(),
        rgb2 = tinycolor( color2 ).toRgb(),
        p = amount / 100,
        w = 2 * p - 1,
        a = rgb2.a - rgb1.a;
      w1 = -1 == w * a ? w : ( w + a ) / ( 1 + w * a ), w1 = ( w1 + 1 ) / 2;
      var w2 = 1 - w1,
        rgba = {
          r: rgb2.r * w1 + rgb1.r * w2,
          g: rgb2.g * w1 + rgb1.g * w2,
          b: rgb2.b * w1 + rgb1.b * w2,
          a: rgb2.a * p + rgb1.a * ( 1 - p )
        };
      return tinycolor( rgba )
    }, tinycolor.readability = function( color1, color2 ) {
      var c1 = tinycolor( color1 ),
        c2 = tinycolor( color2 );
      return ( Math.max( c1.getLuminance(), c2.getLuminance() ) + .05 ) / ( Math.min( c1.getLuminance(), c2.getLuminance() ) + .05 )
    }, tinycolor.isReadable = function( color1, color2, wcag2 ) {
      var wcag2Parms, out, readability = tinycolor.readability( color1, color2 );
      switch ( out = !1, wcag2Parms = validateWCAG2Parms( wcag2 ), wcag2Parms.level + wcag2Parms.size ) {
        case "AAsmall":
        case "AAAlarge":
          out = readability >= 4.5;
          break;
        case "AAlarge":
          out = readability >= 3;
          break;
        case "AAAsmall":
          out = readability >= 7
      }
      return out
    }, tinycolor.mostReadable = function( baseColor, colorList, args ) {
      var readability, includeFallbackColors, level, size, bestColor = null,
        bestScore = 0;
      args = args || {}, includeFallbackColors = args.includeFallbackColors, level = args.level, size = args.size;
      for ( var i = 0; i < colorList.length; i++ ) readability = tinycolor.readability( baseColor, colorList[ i ] ), readability > bestScore && ( bestScore = readability, bestColor = tinycolor( colorList[ i ] ) );
      return tinycolor.isReadable( baseColor, bestColor, {
        level: level,
        size: size
      } ) || !includeFallbackColors ? bestColor : ( args.includeFallbackColors = !1, tinycolor.mostReadable( baseColor, [ "#fff", "#000" ], args ) )
    };
    var names = tinycolor.names = {
        aliceblue: "f0f8ff",
        antiquewhite: "faebd7",
        aqua: "0ff",
        aquamarine: "7fffd4",
        azure: "f0ffff",
        beige: "f5f5dc",
        bisque: "ffe4c4",
        black: "000",
        blanchedalmond: "ffebcd",
        blue: "00f",
        blueviolet: "8a2be2",
        brown: "a52a2a",
        burlywood: "deb887",
        burntsienna: "ea7e5d",
        cadetblue: "5f9ea0",
        chartreuse: "7fff00",
        chocolate: "d2691e",
        coral: "ff7f50",
        cornflowerblue: "6495ed",
        cornsilk: "fff8dc",
        crimson: "dc143c",
        cyan: "0ff",
        darkblue: "00008b",
        darkcyan: "008b8b",
        darkgoldenrod: "b8860b",
        darkgray: "a9a9a9",
        darkgreen: "006400",
        darkgrey: "a9a9a9",
        darkkhaki: "bdb76b",
        darkmagenta: "8b008b",
        darkolivegreen: "556b2f",
        darkorange: "ff8c00",
        darkorchid: "9932cc",
        darkred: "8b0000",
        darksalmon: "e9967a",
        darkseagreen: "8fbc8f",
        darkslateblue: "483d8b",
        darkslategray: "2f4f4f",
        darkslategrey: "2f4f4f",
        darkturquoise: "00ced1",
        darkviolet: "9400d3",
        deeppink: "ff1493",
        deepskyblue: "00bfff",
        dimgray: "696969",
        dimgrey: "696969",
        dodgerblue: "1e90ff",
        firebrick: "b22222",
        floralwhite: "fffaf0",
        forestgreen: "228b22",
        fuchsia: "f0f",
        gainsboro: "dcdcdc",
        ghostwhite: "f8f8ff",
        gold: "ffd700",
        goldenrod: "daa520",
        gray: "808080",
        green: "008000",
        greenyellow: "adff2f",
        grey: "808080",
        honeydew: "f0fff0",
        hotpink: "ff69b4",
        indianred: "cd5c5c",
        indigo: "4b0082",
        ivory: "fffff0",
        khaki: "f0e68c",
        lavender: "e6e6fa",
        lavenderblush: "fff0f5",
        lawngreen: "7cfc00",
        lemonchiffon: "fffacd",
        lightblue: "add8e6",
        lightcoral: "f08080",
        lightcyan: "e0ffff",
        lightgoldenrodyellow: "fafad2",
        lightgray: "d3d3d3",
        lightgreen: "90ee90",
        lightgrey: "d3d3d3",
        lightpink: "ffb6c1",
        lightsalmon: "ffa07a",
        lightseagreen: "20b2aa",
        lightskyblue: "87cefa",
        lightslategray: "789",
        lightslategrey: "789",
        lightsteelblue: "b0c4de",
        lightyellow: "ffffe0",
        lime: "0f0",
        limegreen: "32cd32",
        linen: "faf0e6",
        magenta: "f0f",
        maroon: "800000",
        mediumaquamarine: "66cdaa",
        mediumblue: "0000cd",
        mediumorchid: "ba55d3",
        mediumpurple: "9370db",
        mediumseagreen: "3cb371",
        mediumslateblue: "7b68ee",
        mediumspringgreen: "00fa9a",
        mediumturquoise: "48d1cc",
        mediumvioletred: "c71585",
        midnightblue: "191970",
        mintcream: "f5fffa",
        mistyrose: "ffe4e1",
        moccasin: "ffe4b5",
        navajowhite: "ffdead",
        navy: "000080",
        oldlace: "fdf5e6",
        olive: "808000",
        olivedrab: "6b8e23",
        orange: "ffa500",
        orangered: "ff4500",
        orchid: "da70d6",
        palegoldenrod: "eee8aa",
        palegreen: "98fb98",
        paleturquoise: "afeeee",
        palevioletred: "db7093",
        papayawhip: "ffefd5",
        peachpuff: "ffdab9",
        peru: "cd853f",
        pink: "ffc0cb",
        plum: "dda0dd",
        powderblue: "b0e0e6",
        purple: "800080",
        rebeccapurple: "663399",
        red: "f00",
        rosybrown: "bc8f8f",
        royalblue: "4169e1",
        saddlebrown: "8b4513",
        salmon: "fa8072",
        sandybrown: "f4a460",
        seagreen: "2e8b57",
        seashell: "fff5ee",
        sienna: "a0522d",
        silver: "c0c0c0",
        skyblue: "87ceeb",
        slateblue: "6a5acd",
        slategray: "708090",
        slategrey: "708090",
        snow: "fffafa",
        springgreen: "00ff7f",
        steelblue: "4682b4",
        tan: "d2b48c",
        teal: "008080",
        thistle: "d8bfd8",
        tomato: "ff6347",
        turquoise: "40e0d0",
        violet: "ee82ee",
        wheat: "f5deb3",
        white: "fff",
        whitesmoke: "f5f5f5",
        yellow: "ff0",
        yellowgreen: "9acd32"
      },
      hexNames = tinycolor.hexNames = flip( names ),
      matchers = function() {
        var CSS_INTEGER = "[-\\+]?\\d+%?",
          CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?",
          CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")",
          PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?",
          PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
        return {
          rgb: new RegExp( "rgb" + PERMISSIVE_MATCH3 ),
          rgba: new RegExp( "rgba" + PERMISSIVE_MATCH4 ),
          hsl: new RegExp( "hsl" + PERMISSIVE_MATCH3 ),
          hsla: new RegExp( "hsla" + PERMISSIVE_MATCH4 ),
          hsv: new RegExp( "hsv" + PERMISSIVE_MATCH3 ),
          hsva: new RegExp( "hsva" + PERMISSIVE_MATCH4 ),
          hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
          hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
          hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
        }
      }();
    /*"undefined" != typeof module && module.exports ? module.exports = tinycolor : "function" == typeof define && define.amd ? define(function() {
    	return tinycolor
    }) : */

    window.tinycolor = tinycolor
  }();;

  var random_color_step = 1;
  var custom_style_set = false;
  var current_edit_img = null;
  var allow_upload_img = null;
  window.current_edit_msg_id = '';
  // sherlockl
  //var current_editor;
  window.replace_full_color = false;
  var replace_clear_interval = null;

  function strip_stack_span( html ) {
    var docObj = $( '<div>' + html + '</div>' );
    docObj.find( 'li,colgroup,a' ).each( function() {
      if ( $.trim( $( this ).text() ) == "" && $( this ).find( 'img' ).size() == 0 ) {
        $( this ).remove();
      }
    } );
    var has_secspan = false;
    do {
      has_secspan = false;
      docObj.find( 'span:has(span)' ).each( function( i ) {
        var innerobj = $( this ).find( '> span' );
        if ( innerobj.size() > 1 ) {
          $( this ).find( 'span' ).each( function() {
            if ( $.trim( $( this ).text() ) == "" ) {
              $( this ).replaceWith( $( this ).html() );
            }
          } )
          return;
        } else if ( innerobj.size() == 0 ) {
          return;
        }
        if ( $.trim( $( this ).text() ) == $.trim( innerobj.text() ) ) {
          has_secspan = true;
          var style = $( this ).attr( 'style' );
          var innserstyle = innerobj.attr( 'style' );
          var newStyle = '';
          if ( style && style != "" ) {
            newStyle += ';' + style;
          }
          if ( innserstyle && innserstyle != "" ) {
            newStyle += ';' + innserstyle;
          }
          var new_html = '';
          $( this ).find( '> *' ).each( function() {
            if ( this.tagName == "SPAN" ) {
              new_html += $( innerobj ).html();
            } else {
              new_html += $( this ).prop( 'outerHTML' );
            }
          } );
          $( this ).attr( 'style', newStyle ).html( new_html );
        }
      } );
    } while ( has_secspan );
    return docObj.html();
  }

  function strip_tags( input, allowed ) {
    allowed = ( ( ( allowed || '' ) + '' ).toLowerCase().match( /<[a-z][a-z0-9]*>/g ) || [] ).join( '' );
    var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
      commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
    return input.replace( commentsAndPhpTags, '' ).replace( tags, function( $0, $1 ) {
      return allowed.indexOf( '<' + $1.toLowerCase() + '>' ) > -1 ? $0 : '';
    } );
  }

  function htmlspecialchars_decode( string, quote_style ) {
    var optTemp = 0,
      i = 0,
      noquotes = false;
    if ( typeof quote_style === 'undefined' ) {
      quote_style = 2;
    }
    string = string.toString().replace( /&lt;/g, '<' ).replace( /&gt;/g, '>' );
    var OPTS = {
      'ENT_NOQUOTES': 0,
      'ENT_HTML_QUOTE_SINGLE': 1,
      'ENT_HTML_QUOTE_DOUBLE': 2,
      'ENT_COMPAT': 2,
      'ENT_QUOTES': 3,
      'ENT_IGNORE': 4
    };
    if ( quote_style === 0 ) {
      noquotes = true;
    }
    if ( typeof quote_style !== 'number' ) {
      quote_style = [].concat( quote_style );
      for ( i = 0; i < quote_style.length; i++ ) {
        if ( OPTS[ quote_style[ i ] ] === 0 ) {
          noquotes = true;
        } else if ( OPTS[ quote_style[ i ] ] ) {
          optTemp = optTemp | OPTS[ quote_style[ i ] ];
        }
      }
      quote_style = optTemp;
    }
    if ( quote_style & OPTS.ENT_HTML_QUOTE_SINGLE ) {
      string = string.replace( /&#0*39;/g, "'" );
    }
    if ( !noquotes ) {
      string = string.replace( /&quot;/g, '"' );
    }
    string = string.replace( /&amp;/g, '&' );
    return string;
  }

  function str_replace( search, replace, subject, count ) {
    var i = 0,
      j = 0,
      temp = '',
      repl = '',
      sl = 0,
      fl = 0,
      f = [].concat( search ),
      r = [].concat( replace ),
      s = subject,
      ra = Object.prototype.toString.call( r ) === '[object Array]',
      sa = Object.prototype.toString.call( s ) === '[object Array]';
    s = [].concat( s );
    if ( count ) {
      this.window[ count ] = 0;
    }
    for ( i = 0, sl = s.length; i < sl; i++ ) {
      if ( s[ i ] === '' ) {
        continue;
      }
      for ( j = 0, fl = f.length; j < fl; j++ ) {
        temp = s[ i ] + '';
        repl = ra ? ( r[ j ] !== undefined ? r[ j ] : '' ) : r[ 0 ];
        s[ i ] = ( temp ).split( f[ j ] ).join( repl );
        if ( count && s[ i ] !== temp ) {
          this.window[ count ] += ( temp.length - s[ i ].length ) / f[ j ].length;
        }
      }
    }
    return sa ? s : s[ 0 ];
  }

  function getSelectionHtml() {
    var range = current_editor.selection.getRange();
    range.select();
    var selectionObj = current_editor.selection.getNative();
    var rangeObj = selectionObj.getRangeAt( 0 );
    var docFragment = rangeObj.cloneContents();
    var testDiv = document.createElement( "div" );
    testDiv.appendChild( docFragment );
    var selectHtml = testDiv.innerHTML;
    if ( selectHtml == "" ) {
      return "";
    } else {
      return parse135EditorHtml( selectHtml );
    }
  }

  window.getDealingHtml = function() {
    var html = getSelectionHtml();
    if ( html == "" ) {
      if ( current_editor.currentActive135Item() ) {
        return $( current_editor.currentActive135Item() ).html();
      } else {
        return getEditorHtml();
      }
    } else {
      return html;
    }
  };

  function setDealingHtml( newHtml ) {
    newHtml = $.trim( newHtml );
    var html = getSelectionHtml();
    if ( html != "" ) {
      insertHtml( newHtml );
      custom_style_set = true;
      current_editor.undoManger.save();
      return;
    } else if ( current_editor.currentActive135Item() ) {
      $( current_editor.currentActive135Item() ).html( newHtml );
      current_editor.undoManger.save();
      return;
    } else {
      current_editor.setContent( newHtml );
      current_editor.undoManger.save();
      return;
    }
  }

  function parse135EditorHtml( html, outer_falg ) {
    html = parseMmbizUrl( html );
    var htmlObj = $( '<div>' + html + ' </div>' );
    var htmlTable = htmlObj.find( 'table' );
    htmlObj.find( 'h1,h2,h3,h4,h5,h6,h7' ).css( 'font-weight', 'bold' );
    htmlObj.find( 'h1' ).each( function() {
      if ( !this.style.fontSize ) {
        this.style.fontSize = '32px';
      }
      if ( !this.style.lineHeight ) {
        this.style.lineHeight = '36px';
      }
    } );
    htmlObj.find( 'h2' ).each( function() {
      if ( !this.style.fontSize ) {
        this.style.fontSize = '27px';
      }
      if ( !this.style.lineHeight ) {
        this.style.lineHeight = '29px';
      }
    } );
    htmlObj.find( 'h3' ).each( function() {
      if ( !this.style.fontSize ) {
        this.style.fontSize = '19px';
      }
      if ( !this.style.lineHeight ) {
        this.style.lineHeight = '23px';
      }
    } );
    htmlObj.find( 'h4' ).each( function() {
      if ( !this.style.fontSize ) {
        this.style.fontSize = '16px';
      }
      if ( !this.style.lineHeight ) {
        this.style.lineHeight = '19px';
      }
    } );
    htmlObj.find( 'h5' ).each( function() {
      if ( !this.style.fontSize ) {
        this.style.fontSize = '14px';
      }
      if ( !this.style.lineHeight ) {
        this.style.lineHeight = '18px';
      }
    } );
    htmlObj.find( 'h6' ).each( function() {
      if ( !this.style.fontSize ) {
        this.style.fontSize = '12px';
      }
      if ( !this.style.lineHeight ) {
        this.style.lineHeight = '14px';
      }
    } );
    htmlObj.find( '.135editor' ).each( function() {
      $( this ).css( {
        'border': '0 none',
        'padding': 0
      } );
    } );
    htmlObj.find( '.135article' ).each( function() {
      $( this ).removeAttr( 'style' );
      $( this ).removeAttr( 'class' );
    } );
    htmlObj.find( 'p' ).css( 'white-space', 'normal' );
    htmlObj.find( '*' ).each( function() {
      if ( $( this ).hasClass( 'article135' ) ) {
        return;
      } else if ( this.tagName == "IMG" || this.tagName == "BR" || this.tagName == "H1" || this.tagName == "H2" || this.tagName == "H3" || this.tagName == "H4" || this.tagName == "H5" || this.tagName == "H6" ) {
        return;
      } else if ( this.tagName == "P" || this.tagName == "STRONG" || this.tagName == "SPAN" || this.tagName == "B" || this.tagName == "EM" || this.tagName == "I" ) {
        return;
      } else if ( this.tagName == "OL" || this.tagName == "UL" || this.tagName == "DL" ) {
        this.style.margin = '0px';
        this.style.padding = '0 0 0 30px';
        return;
      }
      this.style.boxSizing = 'border-box';
      if ( this.style.padding == "" && this.style.paddingLeft == "" && this.style.paddingRight == "" && this.style.paddingTop == "" && this.style.paddingBottom == "" ) {
        this.style.padding = '0px';
      }
      if ( this.style.margin == "" && this.style.marginLeft == "" && this.style.marginRight == "" && this.style.marginTop == "" && this.style.marginBottom == "" ) {
        this.style.margin = '0px';
      }
    } );
    htmlObj.find( '*' ).each( function() {
      if ( this.style.transform ) {
        setElementTransform( this, this.style.transform );
      }
    } );
    var html = htmlObj.html();
    if ( $.trim( html ) == "" ) {
      return "";
    }
    if ( htmlObj.find( '.article135' ).size() > 0 ) {
      var childs = htmlObj.find( '> *' );
      if ( childs.size() == 1 && childs.eq( 0 ).hasClass( 'article135' ) ) {
        return htmlObj.html();
      } else {
        htmlObj.find( '.article135' ).each( function() {
          var inner_style = $( this ).attr( 'style' );
          if ( typeof( inner_style ) == 'undefined' || inner_style == '' ) {
            $( this ).replaceWith( $( this ).html() );
          }
        } );
      }
    }
    html = htmlObj.prop( "innerHTML" );
    html = html.replace( 'transform:', 'transform: ' );
    return html;
  }

  function getEditorHtml() {
    $( current_editor.selection.document ).find( 'p' ).each( function() {
      if ( $.trim( $( this ).html() ) == "&nbsp;" ) {
        $( this ).html( '<br/>' );
      }
      if ( $.trim( $( this ).text() ) == "" ) {
        if ( $( this ).find( 'img' ).size() > 0 ) {
          return;
        }
        if ( $( this ).find( 'br' ).size() > 0 ) {
          $( this ).html( '<br/>' );
        } else {
          if ( this.style.clear != "both" ) {
            $( this ).remove();
          }
        }
      }
    } );
    var html = parse135EditorHtml( current_editor.getContent() );
    return '<section class="article135" label="powered by 135editor.com" style="font-family:微软雅黑;font-size:16px;">' + html + '</section>';
  }

  function setElementTransform( dom, transform ) {
    if ( transform == "none" ) return;
    dom.style.position = 'static';
    var sty = $( dom ).attr( 'style' );
    sty = sty.replace( /\s*[^\-]transform\s*:[A-Za-z0-9_%,.\-\(\)\s]*;/gim, '' );
    sty = sty.replace( /\s*-[a-z]+-transform\s*:[A-Za-z0-9_%,.\-\(\)\s]*;/gim, '' );
    sty = sty + ';transform: ' + transform + ';-webkit-transform: ' + transform + ';-moz-transform: ' + transform + ';-ms-transform: ' + transform + ';-o-transform: ' + transform + '; box-sizing: border-box;';
    sty = sty.replace( ';;', ';' );
    $( dom ).attr( 'style', sty );
    $( dom ).parent().css( {
      'box-sizing': 'border-box',
      'display': 'block',
      'position': 'static'
    } );
  }

  function parseMmbizUrl( html ) {
    html = html.replace( /https:\/mmbiz./g, 'https://mmbiz.' );
    html = html.replace( /http:\/\/mmbiz.qpic.cn/g, 'https://mmbiz.qlogo.cn' );
    html = html.replace( /https:\/\/mmbiz.qpic.cn/g, 'https://mmbiz.qlogo.cn' );
    html = html.replace( /http:\/\/mmbiz.qlogo.cn/g, 'https://mmbiz.qlogo.cn' );
    return html;
  }

  function setEditorHtml( newHtml ) {
    newHtml = strip_stack_span( newHtml );
    newHtml = parseMmbizUrl( newHtml );
    current_editor.undoManger.save();
    current_editor.setContent( newHtml );
    current_editor.undoManger.save();
  }

  function insertHtml( html ) {
    html = parseMmbizUrl( html ).replace( /\r|\n/g, '' );;

    var tempObj = $( '<div>' + html + '</div>' );
    $( 'button.brushStyle', tempObj ).remove();
    html = tempObj.html();

    var select_html = getSelectionHtml();
    if ( select_html != "" ) {
      select_html = strip_tags( select_html, '<br><p><h1><h2><h3><h4><h5><h6><img>' );
      var select_obj = $( '<div>' + select_html + '</div>' );
      select_obj.find( '*' ).each( function() {
        $( this ).removeAttr( 'style' );
        $( this ).removeAttr( 'class' );
        $( this ).removeAttr( 'placeholder' );
      } );
      var obj = $( '<div>' + html + '</div>' );
      obj.find( '> .135editor' ).siblings( 'p' ).each( function( i ) {
        if ( $( this ).html() == "" || $( this ).html() == "&nbsp;" || $( this ).html() == "<br>" || $( this ).html() == "<br/>" ) {
          if ( typeof $( this ).attr( 'style' ) == 'undefined' ) {
            $( this ).remove();
          }
        }
      } );
      select_obj.find( 'h1,h2,h3,h4,h5,h6' ).each( function( i ) {
        var title = obj.find( '.135title' ).eq( i );
        if ( title && title.size() > 0 ) {
          title.html( $.trim( $( this ).text() ) );
          $( this ).remove();
        } else {
          $( this ).replaceWith( '<p>' + $( this ).text() + '</p>' );
        }
      } );
      var bgimg_size = obj.find( '.135bg' ).size();
      select_obj.find( 'img' ).each( function( i ) {
        var bgimg = obj.find( '.135bg' ).eq( i );
        if ( bgimg && bgimg.size() > 0 ) {
          bgimg.css( 'background-image', 'url(' + $( this ).attr( 'src' ) + ')' );
          $( this ).remove();
        }
      } );
      select_obj.find( 'img' ).each( function( i ) {
        var img = obj.find( 'img' ).eq( i );
        if ( img && img.size() > 0 ) {
          img.attr( 'src', $( this ).attr( 'src' ) );
          $( this ).remove();
        }
      } );
      var brushs = obj.find( '.135brush' );
      var total = brushs.size();
      if ( total > 0 ) {
        if ( total == 1 ) {
          var brush_item = obj.find( '.135brush:first' );
          if ( brush_item.data( 'brushtype' ) == 'text' ) {
            brush_item.html( $.trim( select_obj.text() ) );
          } else {
            select_obj.contents().each( function( i ) {
              var $this = this;
              if ( this.tagName == "IMG" ) {
                return;
              };
              if ( $.trim( $( $this ).text() ) == "" || this.tagName == 'BR' || $( this ).html() == "" || $( this ).html() == "&nbsp;" || $( this ).html() == "<br>" || $( this ).html() == "<br/>" ) {
                $( this ).remove();
              }
            } );
            var style = brush_item.data( 'style' );
            if ( style ) {
              select_obj.find( '*' ).each( function() {
                $( this ).attr( 'style', style );
              } );
            }
            var html = select_obj.html();
            if ( html != "" ) {
              brush_item.html( html );
            }
          }
        } else {
          select_obj.contents().each( function( i ) {
            var $this = this;
            if ( $this.nodeType == 3 ) {
              $this = $( '<p>' + $( this ).text() + '</p>' ).get( 0 );
            }
            if ( i < total ) {
              var brush_item = brushs.eq( i );
              if ( brush_item.data( 'brushtype' ) == 'text' ) {
                brush_item.html( $.trim( $( $this ).text() ) );
              } else {
                var style = brush_item.data( 'style' );
                if ( style ) {
                  $( $this ).attr( 'style', style );
                }
                brush_item.empty().append( $( $this ) );
              }
            } else {
              var brush_item = brushs.eq( total - 1 );
              if ( brush_item.data( 'brushtype' ) == 'text' ) {
                brush_item.append( $( $this ).text() );
              } else {
                var style = brush_item.data( 'style' );
                if ( style ) {
                  $( $this ).attr( 'style', style );
                }
                brush_item.append( $( $this ) );
              }
            }
          } );
        }
      }
      html = obj.html();
      current_editor.execCommand( 'insertHtml', html );
      current_editor.undoManger.save();
      return true;
    } else {}
    current_editor.execCommand( 'insertHtml', html );
    current_editor.undoManger.save();
    return true;
  }

  function resetMapUrl() {
    $( current_editor.selection.document ).find( 'img' ).each( function() {
      var $img = $( this );
      var mapurl = $( this ).attr( 'mapurl' );
      if ( mapurl ) {
        var usemap = $( this ).attr( 'usemap' );
        if ( usemap ) {
          $( usemap ).each( function() {
            $( this ).remove();
          } )
        }
        usemap = randomString( 10 );
        $img.attr( 'usemap', usemap );
        $img.after( '<map name="' + usemap + '" id="' + usemap + '" style="margin: 0px; padding: 0px; word-wrap: break-word !important; max-width: 100%; box-sizing: border-box !important;"><area style="margin: 0px; padding: 0px; word-wrap: break-word !important; max-width: 100%; box-sizing: border-box !important;" href="' + mapurl + '" shape="default" target="_blank"/></map>' + '<section>' + '<map name="' + usemap + '" id="' + usemap + '" style="margin: 0px; padding: 0px; word-wrap: break-word !important; max-width: 100%; box-sizing: border-box !important;"><area style="margin: 0px; padding: 0px; word-wrap: break-word !important; max-width: 100%; box-sizing: border-box !important;" href="' + mapurl + '" shape="default" target="_blank"/></map>' + '</section>' );
      }
    } );
  }

  window.setBackgroundColor = function( bgcolor, color, history ) {
    if ( isGreyColor( bgcolor ) ) {
      return false;
    }
    if ( history ) {
      current_editor.undoManger.save();
    }
    var active_item = current_editor.currentActive135Item();
    if ( !replace_full_color && active_item ) {
      parseObject( active_item, bgcolor, color );
      active_item.attr( 'data-color', bgcolor );
      active_item.attr( 'data-custom', bgcolor );
      current_editor.undoManger.save();
      return;
    } else {
      if ( !replace_full_color ) {
        return;
      }
      clean_135helper();
      parseObject( $( current_editor.selection.document ), bgcolor, color );
      $( current_editor.selection.document ).find( '.135editor' ).each( function() {
        $( this ).attr( 'data-color', bgcolor );
      } );
    }
    if ( history ) {
      current_editor.undoManger.save();
    }
    return;
  }

  function parseObject( obj, bgcolor, color ) {
    if ( isGreyColor( bgcolor ) ) {
      return false;
    }
    obj.find( "*" ).each( function() {
      if ( !this.nodeName || this.nodeName == "HTML" || this.nodeName == "HEAD" || this.nodeName == "STYLE" || this.nodeName == "LINK" || this.nodeName == "BODY" ) {
        return;
      }
      if ( this.nodeName == "HR" || this.nodeName == "hr" ) {
        var style = $( this ).attr( 'style' );
        $( this ).attr( 'style', style + ';border-color:' + bgcolor + ';' );
        return;
      }
      if ( this.nodeName == "" || $( this ).attr( 'style' ) == "" ) {
        return;
      }
      if ( 0 ) {
        if ( $( this ).hasClass( '135editor' ) && $( this ).attr( 'data-custom' ) ) {
          return;
        }
        if ( replace_full_color ) {
          var p135items = $( this ).parents( '.135editor' );
          for ( var i = 0; i < p135items.size(); i++ ) {
            if ( p135items.eq( i ).attr( 'data-custom' ) ) {
              return;
            }
          }
        }
      }
      if ( $( this ).attr( 'data-ct' ) == 'fix' ) {
        return;
      }
      var oldColor = $( this ).parents( '.135editor:first' ).attr( 'data-color' );
      var style = $( this ).attr( 'style' );
      if ( oldColor == bgcolor ) {
        return;
      }
      if ( oldColor && style && style.indexOf( 'text-shadow' ) >= 0 ) {
        var newstyle = str_replace( rgb2hex( oldColor ), bgcolor, style );
        newstyle = str_replace( hex2rgb( oldColor ), bgcolor, newstyle );
        $( this ).attr( 'style', newstyle );
      }
      var persent = $( this ).attr( 'data-clessp' ) ? $( this ).attr( 'data-clessp' ) : '50%';
      var hasSetBgColor = false;
      var txt_color;
      var bgC = $( this ).get( 0 ).style.backgroundColor;
      if ( !bgC || bgC === 'initial' || bgC === 'transparent' || bgC === "" ) {
        var fc = $( this ).get( 0 ).style.color;
        if ( fc && fc != "" && fc != 'inherit' && !isGreyColor( fc ) ) {
          if ( $( this ).attr( 'data-txtless' ) ) {
            var txtpersent = $( this ).attr( 'data-txtlessp' ) ? $( this ).attr( 'data-txtlessp' ) : '30%';
            txt_color = getColor( rgb2hex( bgcolor ), $( this ).attr( 'data-txtless' ), txtpersent );
            $( this ).css( 'color', txt_color );
          } else if ( isLightenColor( bgcolor ) ) {
            txt_color = getColor( rgb2hex( bgcolor ), 'darken', persent );
            $( this ).css( 'color', txt_color );
          } else {
            var parentBgColor = getPrarentBgColor( $( this ) );
            if ( parentBgColor == bgcolor ) {
              txt_color = getColor( rgb2hex( bgcolor ), 'lighten', persent );
              $( this ).css( 'color', txt_color );
            } else {
              $( this ).css( 'color', bgcolor );
            }
          }
        }
      } else {
        if ( $( this ).attr( 'data-bgless' ) ) {
          var bgpersent = $( this ).attr( 'data-bglessp' ) ? $( this ).attr( 'data-bglessp' ) : '30%';
          var bg_color;
          if ( $( this ).attr( 'data-bgless' ) == "true" || $( this ).attr( 'data-bgless' ) == true ) {
            if ( isLightenColor( bgcolor ) ) {
              bg_color = getColor( rgb2hex( bgcolor ), 'darken', bgpersent );
              bg_color = getColor( rgb2hex( bg_color ), 'saturate', '20%' );
            } else {
              bg_color = getColor( rgb2hex( bgcolor ), 'lighten', bgpersent );
            }
          } else {
            bg_color = getColor( rgb2hex( bgcolor ), $( this ).attr( 'data-bgless' ), bgpersent );
          }
          if ( $( this ).attr( 'data-bgopacity' ) ) {
            bg_color = getColor( rgb2hex( bg_color ), 'fadeout', $( this ).attr( 'data-bgopacity' ) );
          }
          hasSetBgColor = true;
          $( this ).css( 'backgroundColor', bg_color );
          if ( isLightenColor( bg_color ) ) {
            txt_color = getColor( rgb2hex( bg_color ), 'darken', persent );
            txt_color = getColor( rgb2hex( txt_color ), 'saturate', '20%' );
          } else {
            txt_color = color;
          }
          $( this ).css( 'color', txt_color );
        } else if ( $( this ).attr( 'data-bgopacity' ) ) {
          var bg_color;
          bg_color = getColor( rgb2hex( bgcolor ), 'fadeout', $( this ).attr( 'data-bgopacity' ) );
          if ( isLightenColor( bg_color ) ) {
            txt_color = getColor( rgb2hex( bg_color ), 'darken', persent )
          } else {
            txt_color = color;
          }
          $( this ).css( 'backgroundColor', bg_color );
          $( this ).css( 'color', txt_color );
        } else if ( !isGreyColor( bgC ) ) {
          hasSetBgColor = true;
          $( this ).css( 'backgroundColor', bgcolor );
          var fc = $( this ).get( 0 ).style.color;
          if ( fc != 'inherit' ) {
            if ( isLightenColor( bgcolor ) ) {
              txt_color = getColor( rgb2hex( bgcolor ), 'darken', persent )
            } else {
              txt_color = color;
            }
            $( this ).css( 'color', txt_color );
          }
        } else {
          var fc = $( this ).get( 0 ).style.color;
          if ( fc && fc != "" && fc != 'inherit' && !isGreyColor( fc ) ) {
            if ( $( this ).css( 'backgroundColor' ) != bgcolor ) {
              $( this ).css( 'color', bgcolor );
            }
          }
        }
      }
      if ( $( this ).attr( 'data-bcless' ) ) {
        var bc_color = bgcolor;
        if ( isLightenColor( bgcolor ) ) {
          var persent = $( this ).attr( 'data-bclessp' ) ? $( this ).attr( 'data-bclessp' ) : '20%';
          if ( $( this ).attr( 'data-bcless' ) == 'darken' ) {
            bc_color = getColor( rgb2hex( bgcolor ), 'darken', persent );
            bc_color = getColor( rgb2hex( bc_color ), 'saturate', '30%' );
          } else {
            bc_color = getColor( rgb2hex( bgcolor ), 'darken', persent );
            if ( $( this ).attr( 'data-bcless' ) && $( this ).attr( 'data-bcless' ) != 'auto' && $( this ).attr( 'data-bcless' ) != 'true' ) {
              bc_color = getColor( rgb2hex( bgcolor ), $( this ).attr( 'data-bcless' ), persent );
            }
          }
        } else {
          var persent = $( this ).attr( 'data-bclessp' ) ? $( this ).attr( 'data-bclessp' ) : '20%';
          if ( $( this ).attr( 'data-bcless' ) == 'lighten' || $( this ).attr( 'data-bcless' ) == 'auto' || $( this ).attr( 'data-bcless' ) == 'true' ) {
            bc_color = getColor( rgb2hex( bgcolor ), 'lighten', persent );
            bc_color = getColor( rgb2hex( bc_color ), 'desaturate', '20%' );
            bc_color = getColor( rgb2hex( bc_color ), 'fadein', '20%' );
          } else {
            if ( $( this ).attr( 'data-bcless' ) && $( this ).attr( 'data-bcless' ) != 'auto' && $( this ).attr( 'data-bcless' ) != 'true' ) {
              bc_color = getColor( rgb2hex( bgcolor ), $( this ).attr( 'data-bcless' ), persent );
            }
          }
        }
        if ( $( this ).attr( 'data-bdopacity' ) ) {
          bc_color = getColor( rgb2hex( bc_color ), 'fadeout', $( this ).attr( 'data-bdopacity' ) );
        }
        if ( this.style.borderBottomColor || this.style.borderTopColor || this.style.borderLeftColor || this.style.borderRightColor ) {
          if ( this.style.borderBottomColor != 'transparent' && this.style.borderBottomColor != 'initial' ) {
            this.style.borderBottomColor = bc_color;
          }
          if ( this.style.borderTopColor != 'transparent' && this.style.borderTopColor != 'initial' ) {
            this.style.borderTopColor = bc_color;
          }
          if ( this.style.borderLeftColor != 'transparent' && this.style.borderLeftColor != 'initial' ) {
            this.style.borderLeftColor = bc_color;
          }
          if ( this.style.borderRightColor != 'transparent' && this.style.borderRightColor != 'initial' ) {
            this.style.borderRightColor = bc_color;
          }
        } else {
          if ( this.style.borderColor !== 'transparent' && this.style.borderColor !== 'initial' ) {
            this.style.borderColor = bc_color;
          }
        }
      } else {
        var bc_color = bgcolor;
        if ( $( this ).attr( 'data-bdopacity' ) ) {
          bc_color = getColor( rgb2hex( bgcolor ), 'fadeout', $( this ).attr( 'data-bdopacity' ) );
        }
        if ( this.style.borderBottomColor || this.style.borderTopColor || this.style.borderLeftColor || this.style.borderRightColor ) {
          if ( this.style.borderBottomColor != 'transparent' && this.style.borderBottomColor != 'initial' ) {
            setColor( this, 'borderBottomColor', bc_color );
          }
          if ( this.style.borderTopColor != 'transparent' && this.style.borderTopColor != 'initial' ) {
            setColor( this, 'borderTopColor', bc_color );
          }
          if ( this.style.borderLeftColor != 'transparent' && this.style.borderLeftColor != 'initial' ) {
            setColor( this, 'borderLeftColor', bc_color );
          }
          if ( this.style.borderRightColor != 'transparent' && this.style.borderRightColor != 'initial' ) {
            setColor( this, 'borderRightColor', bc_color );
          }
        } else {
          var c = this.style.borderColor;
          if ( c !== 'transparent' && c !== 'initial' && !isGreyColor( c ) ) {
            this.style.borderColor = bc_color;
          }
        }
      }
      var bgimg = $( this ).css( 'backgroundImage' );
      if ( bgimg.substring( 0, 24 ) == '-webkit-linear-gradient(' ) {
        var colors;
        var type;
        if ( bgimg.substring( 0, 30 ) == '-webkit-linear-gradient(left, ' ) {
          type = 'left';
          colors = bgimg.substring( 30, ( bgimg.length - 1 ) );
        } else if ( bgimg.substring( 0, 29 ) == '-webkit-linear-gradient(top, ' ) {
          type = 'top';
          colors = bgimg.substring( 29, ( bgimg.length - 1 ) );
        } else if ( bgimg.substring( 0, 31 ) == '-webkit-linear-gradient(right, ' ) {
          type = 'right';
          colors = bgimg.substring( 31, ( bgimg.length - 1 ) );
        } else if ( bgimg.substring( 0, 32 ) == '-webkit-linear-gradient(bottom, ' ) {
          type = 'bottom';
          colors = bgimg.substring( 32, ( bgimg.length - 1 ) );
        }
        if ( colors ) {
          var color_arr = colors.split( '),' );
          var txt_color, gradient_color, main_color;
          if ( $( this ).attr( 'data-bgless' ) ) {
            var bgpersent = $( this ).attr( 'data-bglessp' ) ? $( this ).attr( 'data-bglessp' ) : '30%';
            main_color = getColor( rgb2hex( bgcolor ), $( this ).attr( 'data-bgless' ), bgpersent );
          } else if ( isLightenColor( bgcolor ) ) {
            main_color = getColor( rgb2hex( bgcolor ), 'saturate', '20%' );
          } else {
            main_color = getColor( rgb2hex( bgcolor ), 'lighten', '5%' );
            main_color = getColor( rgb2hex( main_color ), 'desaturate', '10%' );
            main_color = getColor( rgb2hex( main_color ), 'fadein', '20%' );
          }
          if ( isLightenColor( main_color ) ) {
            txt_color = getColor( rgb2hex( main_color ), 'darken', '50%' );
            txt_color = getColor( rgb2hex( txt_color ), 'saturate', '30%' );
          } else {
            txt_color = getColor( rgb2hex( main_color ), 'lighten', '50%' );
          }
          if ( $( this ).attr( 'data-gradient' ) ) {
            gradient_color = $( this ).attr( 'data-gradient' );
          } else {
            gradient_color = getColor( rgb2hex( main_color ), 'lighten', '30%' );
          }
          if ( color_arr.length == 3 ) {
            $( this ).css( 'backgroundImage', '-webkit-linear-gradient(' + type + ', ' + main_color + ', ' + gradient_color + ', ' + main_color + ')' );
            $( this ).css( 'color', txt_color );
          } else if ( color_arr.length == 2 ) {
            $( this ).css( 'backgroundImage', '-webkit-linear-gradient(' + type + ', ' + main_color + ', ' + gradient_color + ')' );
            $( this ).css( 'color', txt_color );
          }
        }
      }
    } );
    return obj;
  }

  function parseHtml( html, bgcolor, color ) {
    var obj = $( '<div id="editor-content">' + html + "</div>" );
    obj = parseObject( obj, bgcolor, color );
    var result = obj.html();
    obj = null;
    return result;
  }

  function style_click( id ) {
    var url = 'http://www.135editor.com/editor_styles/click_num';
    ajaxAction( url, {
      id: id
    } );
    return false;
  }

  function setFavorColor( colors, callback ) {
    var url = 'http://www.135editor.com/editor_styles/setFavorColor';
    ajaxAction( url, {
      colors: colors
    }, null, callback );
  }

  function setColor( obj, colorType, color ) {
    var c = $( obj ).css( colorType );
    if ( c === 'transparent' || c === 'initial' ) {
      return;
    } else {
      if ( !isGreyColor( c ) ) {
        $( obj ).css( colorType, color );
      }
    }
  }

  function getPrarentBgColor( $obj ) {
    if ( !$obj.parent().get( 0 ) ) {
      return "";
    }
    if ( $obj.parent().get( 0 ).tagName && $obj.parent().get( 0 ).tagName == 'BODY' ) {
      if ( $obj.parent().get( 0 ).style ) {
        var bgC = $obj.parent().get( 0 ).style.backgroundColor;
        return bgC;
      } else {
        return "";
      }
    }
    if ( $obj.parent().get( 0 ).style ) {
      var bgC = $obj.parent().get( 0 ).style.backgroundColor;
      if ( !bgC || bgC === 'initial' || bgC === 'transparent' || bgC === "" ) {
        return getPrarentBgColor( $obj.parent() );
      } else {
        return bgC;
      }
    } else {
      return "";
    }
  }

  function rgb2hex( color ) {
    rgb = color.match( /^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i );
    return ( rgb && rgb.length === 4 ) ? "#" +
      ( "0" + parseInt( rgb[ 1 ], 10 ).toString( 16 ) ).slice( -2 ) +
      ( "0" + parseInt( rgb[ 2 ], 10 ).toString( 16 ) ).slice( -2 ) +
      ( "0" + parseInt( rgb[ 3 ], 10 ).toString( 16 ) ).slice( -2 ) : color;
  }

  function hex2rgb( color ) {
    var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
    var sColor = color.toLowerCase();
    if ( sColor && reg.test( sColor ) ) {
      if ( sColor.length === 4 ) {
        var sColorNew = "#";
        for ( var i = 1; i < 4; i += 1 ) {
          sColorNew += sColor.slice( i, i + 1 ).concat( sColor.slice( i, i + 1 ) );
        }
        sColor = sColorNew;
      }
      var sColorChange = [];
      for ( var i = 1; i < 7; i += 2 ) {
        sColorChange.push( parseInt( "0x" + sColor.slice( i, i + 2 ) ) );
      }
      return "RGB(" + sColorChange.join( "," ) + ")";
    } else {
      return sColor;
    }
  };

  function isLightenColor( color ) {
    var c = rgb2hex( color );
    var r = ( "" + c.substring( 1, 3 ) );
    var g = ( "" + c.substring( 3, 5 ) );
    var b = ( "" + c.substring( 5, 7 ) );
    if ( r > 'C0' && g > 'C0' && b > 'C0' ) {
      return true;
    } else {
      return false;
    }
  }

  function isGreyColor( color ) {
    var c = rgb2hex( color );
    var r = "" + c.substring( 1, 3 );
    var g = "" + c.substring( 3, 5 );
    var b = "" + c.substring( 5, 7 );
    if ( r == g && g == b ) {
      return true;
    } else {
      return false;
    }
  }

  function getColor( color, type, num ) {
    var str = '';
    var color_obj = tinycolor( color );
    if ( typeof( color_obj[ type ] ) == 'function' ) {
      num = parseInt( num.replace( '%', '' ) );
      return color_obj[ type ]( num ).toString();
    } else if ( type == 'fade' || type == 'fadein' || type == 'fadeout' ) {
      if ( num.indexOf( '%' ) > 0 ) {
        num = num.replace( '%', '' );
        num = parseInt( num ) / 100;
      }
      if ( type == 'fadein' ) {
        num += color_obj.getAlpha( num );
      } else if ( type == 'fadeout' ) {
        num -= color_obj.getAlpha( num );
      }
      return color_obj.setAlpha( num ).toString();
    }
    return color;
  }

  /*function LightenDarkenColor( col, amt ) {
  	var usePound = false;
  	if ( col[ 0 ] == "#" ) {
  		col = col.slice( 1 );
  		usePound = true;
  	}
  	var num = parseInt( col, 16 );
  	var r = ( num >> 16 ) + amt;
  	if ( r > 255 ) r = 255;
  	else if ( r < 0 ) r = 0;
  	var b = ( ( num >> 8 ) & 0x00FF ) + amt;
  	if ( b > 255 ) b = 255;
  	else if ( b < 0 ) b = 0;
  	var g = ( num & 0x0000FF ) + amt;
  	if ( g > 255 ) g = 255;
  	else if ( g < 0 ) g = 0;
  	return ( usePound ? "#" : "" ) + ( g | ( b << 8 ) | ( r << 16 ) ).toString( 16 );
  }*/

  /*function openTplModal() {
  	$( '#templateModal' ).modal( 'show' );
  	$( '#template-modal-body' ).html( '正在加载' ).load( BASEURL + '/editor_styles/myTemplates #my-templates', function() {
  		$( '#my-templates .nav-tabs a:first' ).tab( 'show' )
  	} )
  }*/

  /*function set_style( styles ) {
  	ckeditors[ 'WxMsgContent' ].execCommand( 'removeFormat' );
  	var element = ckeditors[ 'WxMsgContent' ].getSelection().getStartElement();
  	if ( element.getName() == 'img' ) {
  		element.setStyles( styles );
  	} else {
  		var style = new CKEDITOR.style( {
  			element: element.getName(),
  			styles: styles
  		} );
  		ckeditors[ 'WxMsgContent' ].applyStyle( style );
  	}
  }*/

  function getPreferences( idx ) {
    var cookieOpt = current_editor.getPreferences( 'editor135' );
    if ( cookieOpt && cookieOpt[ idx ] ) {
      return cookieOpt[ idx ];
    }
    return null;
  }

  window.setPreferences = function( key, value ) {
    var cookieOpt = current_editor.getPreferences( 'editor135' );
    var obj = {};
    if ( typeof( key ) == "string" ) {
      obj[ key ] = value;
    } else {
      obj = key;
    }
    if ( !cookieOpt ) cookieOpt = {};
    $.extend( cookieOpt, obj );
    current_editor.setPreferences( 'editor135', cookieOpt );
  }

  /*function applyParagraph( type ) {
  	var object;
  	if ( type == 'all' ) {
  		var editor_document = current_editor.selection.document;
  		object = $( editor_document );
  	} else {
  		if ( !current_editor.currentActive135Item() ) return;
  		object = current_editor.currentActive135Item();
  	}
  	$( object ).find( 'p' ).each( function() {
  		$( this ).css( 'lineHeight', $( '#paragraph-lineHeight' ).val() );
  		$( this ).css( 'fontFamily', $( '#paragraph-fontFamily' ).val() );
  		$( this ).css( 'fontSize', $( '#paragraph-fontSize' ).val() );
  		$( this ).css( 'textIndent', $( '#paragraph-textIndent' ).val() );
  		$( this ).css( 'paddingTop', $( '#paragraph-paddingTop' ).val() );
  		$( this ).css( 'paddingBottom', $( '#paragraph-paddingBottom' ).val() );
  	} )
  }*/

  function clean_135helper() {
    var editor_document = current_editor.selection.document;
    $( editor_document ).find( '.135editor' ).each( function() {
      $( this ).css( {
        'border': '0 none',
        'padding': 0
      } );
    } );
    current_editor.sync();
  }

  window.showColorPlan = function( clientY ) {
    if ( current_editor ) {
      var $container = $( current_editor.container );
      var offset = $container.offset();
      var width = $container.width();
      var height = $container.height();
      if ( offset.left + width + $( '#color-plan' ).width() < $( window ).width() ) {
        $( '#color-plan' ).css( 'left', offset.left + width - 5 );
      } else {
        $( '#color-plan' ).css( 'left', offset.left - $( '#color-plan' ).width() );
      }
      if ( clientY ) {
        if ( clientY - $( window ).scrollTop() > $( '#color-plan' ).height() / 2 ) {
          var top = clientY - $( window ).scrollTop() - ( $( '#color-plan' ).height() / 2 );
          if ( $( window ).height() - top > $( '#color-plan' ).height() ) {
            $( '#color-plan' ).css( 'bottom', 'auto' );
            if ( top < offset.top + $container.find( '.edui-editor-toolbarbox' ).height() - $( window ).scrollTop() ) {
              $( '#color-plan' ).css( 'top', offset.top + $container.find( '.edui-editor-toolbarbox' ).height() - $( window ).scrollTop() );
            } else if ( top + $( '#color-plan' ).height() > offset.top + $container.height() - $( window ).scrollTop() ) {
              $( '#color-plan' ).css( 'top', offset.top + $container.height() - $( window ).scrollTop() - $( '#color-plan' ).height() + 20 );
            } else {
              $( '#color-plan' ).css( 'top', top );
            }
          } else {
            $( '#color-plan' ).css( 'top', 'auto' );
            $( '#color-plan' ).css( 'bottom', 0 );
          }
        } else {
          if ( $( window ).scrollTop() < offset.top + $container.find( '.edui-editor-toolbarbox' ).height() ) {
            $( '#color-plan' ).css( 'top', offset.top + $container.find( '.edui-editor-toolbarbox' ).height() - $( window ).scrollTop() );
            $( '#color-plan' ).css( 'bottom', 'auto' );
          } else {
            $( '#color-plan' ).css( 'top', 0 );
            $( '#color-plan' ).css( 'bottom', 'auto' );
          }
        }
      } else {
        $( '#color-plan' ).css( 'top', offset.top + height / 2 - 120 - $( window ).scrollTop() );
      }
      $( '#color-plan' ).show();
    } else {
      $( '#color-plan' ).show();
    }
  };

  function hideColorPlan() {
    $( '#color-plan' ).hide();
  }

  /*function meitu_upload() {
  	if ( true ) {
  		publishController.open_html_dialog( 'meitu-full' );
  		setTimeout( function() {
  			$( '#meitu-full' ).find( '.modal-body .alert' ).remove();
  		}, 6000 );
  		xiuxiu.setLaunchVars( "titleVisible", 0 );
  		xiuxiu.setLaunchVars( "maxFinalWidth", 600 );
  		xiuxiu.setLaunchVars( "customMenu", [ "decorate", "facialMenu", "puzzle" ] );
  		xiuxiu.setLaunchVars( "uploadBtnLabel", "上传", "meitu_full" );
  		xiuxiu.embedSWF( "MeituFullContent", 3, 940, 600, "meitu_full" );
  		xiuxiu.setUploadURL( BASEURL + '/uploadfiles/upload.php' );
  		xiuxiu.setUploadType( 2 );
  		xiuxiu.setUploadDataFieldName( "upload" );
  		xiuxiu.onBeforeUpload = function( data, id ) {
  			var size = data.size;
  			if ( size > 2 * 1024 * 1024 ) {
  				alert( "图片不能超过2M" );
  				return false;
  			}
  			xiuxiu.setUploadArgs( {
  				'return': "xiuxiu",
  				'remote_type': 'wechatUploadimg',
  				'no_thumb': 1,
  				'MIAOCMS[Auth][User]': $.cookie( 'MIAOCMS[Auth][User]' )
  			}, id );
  			return true;
  		};
  		xiuxiu.onUploadResponse = function( data, id ) {
  			try {
  				var json = eval( '(' + data + ')' );
  			} catch ( e ) {
  				alert( data );
  				return;
  			}
  			if ( json.ret == -1 ) {
  				showErrorMessage( json.error );
  			} else {
  				insertHtml( '<img src="' + json.url + '" _src="' + json.url + '">' );
  				publishController.close_dialog();
  			}
  		};
  		xiuxiu.onClose = function( id ) {
  			publishController.close_dialog();
  		}
  	} else {
  		showErrorMessage( '图片拼图属于付费功能。请付费购买图片使用功能后使用' );
  	}
  }*/

  /*function pingtu_upload() {
  	if ( true ) {
  		publishController.open_html_dialog( 'meitu-pingtu' );
  		xiuxiu.setLaunchVars( "titleVisible", 0 );
  		xiuxiu.setLaunchVars( "maxFinalWidth", 600 );
  		xiuxiu.setLaunchVars( "uploadBtnLabel", "上传", "meitu_pingtu" );
  		xiuxiu.embedSWF( "MeituPingTuContent", 2, 700, 500, "meitu_pingtu" );
  		xiuxiu.setUploadURL( BASEURL + '/uploadfiles/upload.php' );
  		xiuxiu.setUploadType( 2 );
  		xiuxiu.setUploadDataFieldName( "upload" );
  		xiuxiu.onBeforeUpload = function( data, id ) {
  			var size = data.size;
  			if ( size > 2 * 1024 * 1024 ) {
  				alert( "图片不能超过2M" );
  				return false;
  			}
  			xiuxiu.setUploadArgs( {
  				'return': "xiuxiu",
  				'remote_type': 'wechatUploadimg',
  				'no_thumb': 1,
  				'MIAOCMS[Auth][User]': $.cookie( 'MIAOCMS[Auth][User]' )
  			}, id );
  			return true;
  		};
  		xiuxiu.onUploadResponse = function( data, id ) {
  			try {
  				var json = eval( '(' + data + ')' );
  			} catch ( e ) {
  				alert( data );
  				return;
  			}
  			if ( json.ret == -1 ) {
  				showErrorMessage( json.error );
  			} else {
  				insertHtml( '<img src="' + json.url + '" _src="' + json.url + '">' );
  				publishController.close_dialog();
  			}
  		};
  		xiuxiu.onClose = function( id ) {
  			publishController.close_dialog();
  		}
  	} else {
  		showErrorMessage( '图片拼图属于付费功能。请付费购买图片使用功能后使用' );
  	}
  }*/

  // sherlock 编辑图片
  window.edit_image = function( url ) {
    try {
      var urlObj = new URL( url );
    } catch ( e ) {
      showErrorMessage( '图片地址异常，无法编辑' );
      return false;
    }
    if ( urlObj.hostname.indexOf( 'bigwe.com' ) > -1 ) { // bigwe的图片可直接进行编辑
      launchXiuxiu( url );
    } else {
      var msg = current_editor.fireEvent( 'showmessage', {
        'id': 'uploading-msg',
        'content': '正在上传您的图片',
        'type': 'info',
        'keepshow': true
      } );
      // 非bigwe的需要先上传到bigwe再启动编辑
      $.ajax( {
        type: 'post',
        url: current_editor.getActionUrl( 'catchimage' ),
        data: {
          source: [ url ]
        },
        success: function( data ) {
          current_editor.fireEvent( 'hidemessage', msg );

          data = typeof data === 'string' ? $.parseJSON( data ) : data;
          var imgObj = {};
          if ( data.list && data.list[ 0 ] && data.list[ 0 ].state === 'SUCCESS' ) {
            imgObj = data.list[ 0 ];
            // 防止重复点击需要重复上传
            if ( window.current_edit_img ) {
              window.current_edit_img.src = imgObj.url;
            }
            launchXiuxiu( imgObj.url );
          } else {
            showErrorMessage( '上传失败，请重新点击编辑' );
          }
        }
      } );
    }

    // 启动美图秀秀
    function launchXiuxiu( url ) {
      publishController.open_html_dialog( 'meitu-beautify' );
      xiuxiu.setLaunchVars( "titleVisible", 0 );
      xiuxiu.setLaunchVars( "maxFinalWidth", 600 );
      xiuxiu.setLaunchVars( "uploadBtnLabel", "完成", "beautify" );
      xiuxiu.embedSWF( "MeituContent", 1, '100%', '100%', "beautify" );
      xiuxiu.setUploadURL( current_editor.getActionUrl( 'uploadimage' ) );
      // 标准上传方式
      xiuxiu.setUploadType( 2 );
      xiuxiu.setUploadDataFieldName( "file" );
      xiuxiu.onBeforeUpload = function( data, id ) {
        var size = data.size;
        if ( size > 2 * 1024 * 1024 ) {
          alert( "图片不能超过2M" );
          return false;
        }
        xiuxiu.setUploadArgs( {
          'return': "xiuxiu",
          'url': url,
          'remote_type': 'wechatUploadimg',
          'no_thumb': 1,
          'MIAOCMS[Auth][User]': $.cookie( 'MIAOCMS[Auth][User]' )
        }, id );
        return true;
      };
      xiuxiu.onInit = function() {
        if ( url ) {
          xiuxiu.loadPhoto( url );
        }
        publishController.focus_close();
      };
      xiuxiu.onUploadResponse = function( data, id ) {
        try {
          var json = eval( '(' + data + ')' );
        } catch ( e ) {
          alert( data );
          return;
        }
        if ( json.state !== 'SUCCESS' ) {
          showErrorMessage( json.error );
        } else {
          if ( url && window.current_edit_img ) {
            var new_url = json.url;
            window.current_edit_img.src = new_url;
            window.current_edit_img.setAttribute( "_src", new_url );
          } else {
            insertHtml( '<img src="' + json.url + '" _src="' + json.url + '">' );
          }
          publishController.close_dialog();
        }
      };
      xiuxiu.onClose = function( id ) {
        publishController.close_dialog();
      }
    }
  };

  ( function( $ ) {
    var pluginName = 'slider',
      initAllSelector = '[data-role=slider], .slider',
      paramKeys = [ 'InitValue', 'Accuracy' ];
    $[ pluginName ] = function( element, options ) {
      if ( !element ) {
        return $()[ pluginName ]( {
          initAll: true
        } );
      }
      var defaults = {
        initValue: 0,
        accuracy: 1
      };
      var plugin = this;
      plugin.settings = {};
      var $element = $( element );
      var complete, marker, currentValuePerc, sliderLength, sliderOffset, sliderStart, sliderEnd, percentPerPixel, markerSize, vertical = false;
      plugin.init = function() {
        plugin.settings = $.extend( {}, defaults, options );
        complete = $( '<div class="complete"></div>' );
        marker = $( '<div class="marker"></div>' );
        complete.appendTo( $element );
        marker.appendTo( $element );
        vertical = $element.hasClass( 'vertical' );
        initGeometry();
        currentValuePerc = correctValuePerc( plugin.settings.initValue );
        placeMarkerByPerc( currentValuePerc );
        marker.on( 'mousedown', function( e ) {
          e.preventDefault();
          startMoveMarker( e );
        } );
        $element.on( 'mousedown', function( e ) {
          e.preventDefault();
          startMoveMarker( e );
        } );
        $element.trigger( 'inited', [ currentValuePerc ] );
      };
      var correctValuePerc = function( value ) {
        var accuracy = plugin.settings.accuracy;
        if ( accuracy === 0 ) {
          return value;
        }
        if ( value === 100 ) {
          return 100;
        }
        value = Math.floor( value / accuracy ) * accuracy + Math.round( value % accuracy / accuracy ) * accuracy;
        if ( value > 100 ) {
          return 100;
        }
        return value;
      };
      var pixToPerc = function( valuePix ) {
        var valuePerc;
        valuePerc = valuePix * percentPerPixel;
        return correctValuePerc( valuePerc );
      };
      var percToPix = function( value ) {
        if ( percentPerPixel === 0 ) {
          return 0;
        }
        return value / percentPerPixel;
      };
      var placeMarkerByPerc = function( valuePerc ) {
        var size, size2;
        if ( vertical ) {
          size = percToPix( valuePerc ) + markerSize;
          size2 = sliderLength - size;
          marker.css( 'top', size2 );
          complete.css( 'height', size );
        } else {
          size = percToPix( valuePerc );
          marker.css( 'left', size );
          complete.css( 'width', size );
        }
      };
      var startMoveMarker = function( e ) {
        $( document ).on( 'mousemove.sliderMarker', function( event ) {
          movingMarker( event );
        } );
        $( document ).on( 'mouseup.sliderMarker', function() {
          $( document ).off( 'mousemove.sliderMarker' );
          $( document ).off( 'mouseup.sliderMarker' );
          $element.data( 'value', currentValuePerc );
          $element.trigger( 'changed', [ currentValuePerc ] );
        } );
        initGeometry();
        movingMarker( e )
      };
      var initGeometry = function() {
        if ( vertical ) {
          sliderLength = $element.height();
          sliderOffset = $element.offset().top;
          markerSize = marker.height();
        } else {
          sliderLength = $element.width();
          sliderOffset = $element.offset().left;
          markerSize = marker.width();
        }
        percentPerPixel = 100 / ( sliderLength - markerSize );
        sliderStart = markerSize / 2;
        sliderEnd = sliderLength - markerSize / 2;
      };
      var movingMarker = function( event ) {
        var cursorPos, percents, valuePix;
        if ( vertical ) {
          cursorPos = event.pageY - sliderOffset;
        } else {
          cursorPos = event.pageX - sliderOffset;
        }
        if ( cursorPos < sliderStart ) {
          cursorPos = sliderStart;
        } else if ( cursorPos > sliderEnd ) {
          cursorPos = sliderEnd;
        }
        if ( vertical ) {
          valuePix = sliderLength - cursorPos - markerSize / 2;
        } else {
          valuePix = cursorPos - markerSize / 2;
        }
        percents = pixToPerc( valuePix );
        placeMarkerByPerc( percents );
        currentValuePerc = percents;
        $element.trigger( 'change', [ currentValuePerc ] );
      };
      plugin.val = function( value ) {
        if ( typeof value !== 'undefined' ) {
          currentValuePerc = correctValuePerc( value );
          placeMarkerByPerc( currentValuePerc );
          return currentValuePerc;
        } else {
          return currentValuePerc;
        }
      };
      plugin.init();
    };
    $.fn[ pluginName ] = function( options ) {
      var elements = options.initAll ? $( initAllSelector ) : this;
      return elements.each( function() {
        var that = $( this ),
          params = {},
          plugin;
        if ( undefined == that.data( pluginName ) ) {
          $.each( paramKeys, function( index, key ) {
            params[ key[ 0 ].toLowerCase() + key.slice( 1 ) ] = that.data( 'param' + key );
          } );
          plugin = new $[ pluginName ]( this, params );
          that.data( pluginName, plugin );
        }
      } );
    };
    $( function() {
      $()[ pluginName ]( {
        initAll: true
      } );
    } );
  } )( jQuery );;

  UE.plugins[ "open135" ] = function() {
    var me = this,
      editor = this;
    //console.log(me)
    var utils = baidu.editor.utils,
      Popup = baidu.editor.ui.Popup,
      Stateful = baidu.editor.ui.Stateful,
      editorui = baidu.editor.ui,
      uiUtils = baidu.editor.ui.uiUtils,
      UIBase = baidu.editor.ui.UIBase;
    var domUtils = baidu.editor.dom.domUtils;
    var editor_document = null;
    domUtils.on( window, 'scroll', function( evt, el ) {
      hideColorPlan();
    } );
    me.addListener( 'autoheightchanged', function( editor ) {
      var container = me.container;
      // 设置样式高度
      //$(container).parent().find('#style-overflow-list').height($(container).height() - 80);
      //$(container).parent().find('#style-overflow-list').height($(window).height() - 100);
    } );
    me.addListener( 'ready', function( editor ) {
      editor_document = me.selection.document;
      var uid = me.uid;
      var container = me.container;
      var width = $( container ).width();
      var style_width = me.options.style_width || 360;
      //container.style.width = (width - style_width) + "px";
      container.style.width = '100%';
      var height = $( container ).height() > 0 ? $( container ).height() : me.options.initialFrameHeight + 60;
      // sherlockl 
      $( container ).parent().css( {
        'position': 'relative',
        //'padding-left': style_width + 'px',
        'padding-left': 0 + 'px',
        'box-sizing': 'border-box',
        'width': '100%'
      } );
      // sherlockl
      /*$('<div></div>').load(me.options.style_url, function() {
      	
      	// 临时修改 之后还原 $('.content-list>.style-div').hide();
      });*/

    } );
  }
  $( document ).on( 'click', function( event ) {
    var object = event.srcElement ? event.srcElement : event.target;
    if ( object && ( $( object ).parents( '#color-plan' ).size() > 0 || $( object ).parents( '.cp-app' ).size() > 0 ) ) {} else {
      hideColorPlan();
    }
  } );
  // sherlockl 插入样式 style_detail_container 为class的下面的li都起作用
  $( document ).on( 'click', '.ui-portlet-list > li, .js_brush_style, .style_detail_container > li', function() {
    var _this = this;
    if ( $( _this ).hasClass( 'js_brush_style' ) ) {
      _this = this.parentElement;
    }

    if ( $( _this ).hasClass( 'ignore' ) ) {
      return false;
    }
    var ret = false;
    var num = parseInt( $( _this ).find( '.autonum:first' ).text() );
    var id = $( _this ).data( 'id' );
    $( _this ).contents().filter( function() {
      return _this.nodeType === 3 && $.trim( $( _this ).text() ) == "";
    } ).remove();
    $( _this ).find( 'p' ).each( function() {
      if ( $.trim( $( _this ).html() ) == "&nbsp;" ) {
        $( _this ).html( '<br/>' );
      }
    } );
    $( _this ).find( '*' ).each( function() {
      if ( $( _this ).attr( 'data-width' ) ) {
        return;
      }
      if ( _this.style.width && _this.style.width != "" ) {
        $( _this ).attr( 'data-width', _this.style.width );
      }
    } );
    var style_item = $( _this ).find( '> .135editor:first' );
    if ( style_item.size() ) {
      if ( style_item.find( '> *' ).size() == 1 && style_item.find( '> *' ).eq( 0 ).hasClass( '135editor' ) ) {
        ret = insertHtml( style_item.html() + "<p><br/></p>" );
      } else {
        var html = style_item.prop( 'outerHTML' );
        ret = insertHtml( html + "<p><br/></p>" );
      }
    } else {
      ret = insertHtml( "<section data-id=\"" + id + "\" class=\"135editor\">" + $( _this ).html() + "<section style=\"display: block; width: 0; height: 0; clear: both;\"></section></section><p><br/></p>" );
    }
    if ( ret ) {
      if ( typeof num != "undefined" ) {
        $( _this ).find( '.autonum:first' ).text( num + 1 );
      }
    }
  } );
  $( document ).on( 'click', '.color-switch', function( event ) {
    $( '.color-switch' ).removeClass( 'active' );
    $( this ).addClass( 'active' );
    var color = $( this ).data( 'color' );
    var bgcolor = $( this ).css( 'backgroundColor' );
    $( '#custom-color-text' ).val( bgcolor ).css( 'backgroundColor', bgcolor );
    if ( !color ) color = '#FFF';
    setBackgroundColor( bgcolor, color, true );
    event.preventDefault();
    event.stopPropagation();
  } );
  if ( typeof( window.showSuccessMessage ) == 'undefined' ) {
    window.showSuccessMessage = function( text ) {
      if ( current_editor ) {
        current_editor.fireEvent( 'showmessage', {
          'id': 'success-msg',
          'content': text,
          'type': 'success',
          'timeout': 4000
        } );
      } else {
        alert( text );
      }
      return true;
    }
  }
  if ( typeof( window.showErrorMessage ) == 'undefined' ) {
    window.showErrorMessage = function( text ) {
      if ( current_editor ) {
        current_editor.fireEvent( 'showmessage', {
          'id': 'error-msg',
          'content': text,
          'type': 'error',
          'timeout': 4000
        } );
      } else {
        alert( text );
      }
      return true;
    }
  }
  if ( typeof( window.ajaxAction ) == 'undefined' ) {
    window.ajaxAction = function( url, postdata, form, callback_func_name, moreags ) {
      if ( url.search( /\?/ ) != -1 ) {
        url += '&inajax=1';
      } else {
        url += '?inajax=1';
      }
      if ( form ) {
        $( ':submit', form ).each( function() {
          var html = $( this ).html();
          $( this ).data( 'html', html ).html( '<img src="http://static.135editor.com//img/ajax/circle_ball.gif"> ' + html ).attr( 'disabled', 'disabled' );
        } );
      }
      $.ajax( {
        type: 'post',
        url: url,
        data: postdata,
        complete: function( XMLHttpRequest, textStatus ) {
          if ( form ) {
            $( ':submit', form ).each( function() {
              var html = $( this ).data( 'html' );
              $( this ).html( html ).removeAttr( 'disabled' );
            } )
          }
        },
        success: function( request ) {
          if ( request.success ) {
            showSuccessMessage( request.success );
          } else if ( request.error && !request.tasks ) {
            showErrorMessage( request.error );
            var errorinfo = '';
            for ( var i in request ) {
              errorinfo += "<span class='ui-state-error ui-corner-all'><span class='ui-icon ui-icon-alert'></span>" + request[ i ] + "</span>";
            }
          }
          if ( form ) {
            $( ':submit', form ).each( function() {
              var html = $( this ).data( 'html' );
              $( this ).html( html ).removeAttr( 'disabled' );
            } )
          }
          if ( typeof( callback_func_name ) == 'function' ) {
            callback_func_name( request );
          } else if ( callback_func_name && rs_callbacks[ callback_func_name ] ) {
            var func = rs_callbacks[ callback_func_name ];
            if ( moreags ) {
              func( request, moreags );
            } else {
              func( request );
            }
          }
          if ( request.tasks ) {
            $( request.tasks ).each( function( i ) {
              var task = request.tasks[ i ];
              if ( task.dotype == "html" ) {
                if ( $( task.selector, form ).size() ) {
                  $( task.selector, form ).html( task.content ).show();
                } else {
                  $( task.selector ).html( task.content ).show();
                }
              } else if ( task.dotype == "value" ) {
                if ( $( task.selector, form ).size() ) {
                  $( task.selector, form ).val( task.content );
                } else {
                  $( task.selector ).val( task.content );
                }
              } else if ( task.dotype == "append" ) {
                $( task.content ).appendTo( task.selector );
              } else if ( task.dotype == "dialog" ) {
                $( task.content ).appendTo( task.selector );
              } else if ( task.dotype == "location" ) {
                window.location.href = task.url;
              } else if ( task.dotype == "reload" ) {
                window.location.reload();
              } else if ( task.dotype == "jquery" ) {
                if ( task.args ) {
                  $( task.selector )[ task.func ]( task.args );
                } else {
                  $( task.selector )[ task.func ]();
                }
              } else if ( task.dotype == "callback" ) {
                var callback = null,
                  thisArg = null;
                eval( "callback= " + task.callback + ";" );
                eval( "thisArg= " + task.thisArg + ";" );
                var args = [];
                for ( var i in task.callback_args ) {
                  args[ args.length ] = task.callback_args[ i ];
                }
                if ( callback ) {
                  callback.apply( thisArg, args );
                }
              }
            } );
          }
        },
        dataType: "json"
      } );
      return false;
    }
  };
  /**!
   * MixItUp v2.1.9
   *
   * @copyright Copyright 2015 KunkaLabs Limited.
   * @author    KunkaLabs Limited.
   * @link      https://mixitup.kunkalabs.com
   *
   * @license   Commercial use requires a commercial license.
   *            https://mixitup.kunkalabs.com/licenses/
   *
   *            Non-commercial use permitted under terms of CC-BY-NC license.
   *            http://creativecommons.org/licenses/by-nc/3.0/
   */
  ! function( a, b ) {
    a.MixItUp = function() {
      var b = this;
      b._execAction( "_constructor", 0 ), a.extend( b, {
        selectors: {
          target: ".mix",
          filter: ".filter",
          sort: ".sort"
        },
        animation: {
          enable: !0,
          // modify by sherlockl 动画卡顿
          effects: "fade scale",
          duration: 600,
          easing: "ease",
          perspectiveDistance: "3000",
          perspectiveOrigin: "50% 50%",
          queue: !0,
          queueLimit: 1,
          animateChangeLayout: !1,
          animateResizeContainer: !0,
          animateResizeTargets: !1,
          staggerSequence: !1,
          reverseOut: !1
        },
        callbacks: {
          onMixLoad: !1,
          onMixStart: !1,
          onMixBusy: !1,
          onMixEnd: !1,
          onMixFail: !1,
          _user: !1
        },
        controls: {
          enable: !0,
          live: !1,
          toggleFilterButtons: !1,
          toggleLogic: "or",
          activeClass: "active"
        },
        layout: {
          display: "inline-block",
          containerClass: "",
          containerClassFail: "fail"
        },
        load: {
          filter: "all",
          sort: !1
        },
        _$body: null,
        _$container: null,
        _$targets: null,
        _$parent: null,
        _$sortButtons: null,
        _$filterButtons: null,
        _suckMode: !1,
        _mixing: !1,
        _sorting: !1,
        _clicking: !1,
        _loading: !0,
        _changingLayout: !1,
        _changingClass: !1,
        _changingDisplay: !1,
        _origOrder: [],
        _startOrder: [],
        _newOrder: [],
        _activeFilter: null,
        _toggleArray: [],
        _toggleString: "",
        _activeSort: "default:asc",
        _newSort: null,
        _startHeight: null,
        _newHeight: null,
        _incPadding: !0,
        _newDisplay: null,
        _newClass: null,
        _targetsBound: 0,
        _targetsDone: 0,
        _queue: [],
        _$show: a(),
        _$hide: a()
      } ), b._execAction( "_constructor", 1 )
    }, a.MixItUp.prototype = {
      constructor: a.MixItUp,
      _instances: {},
      _handled: {
        _filter: {},
        _sort: {}
      },
      _bound: {
        _filter: {},
        _sort: {}
      },
      _actions: {},
      _filters: {},
      extend: function( b ) {
        for ( var c in b ) a.MixItUp.prototype[ c ] = b[ c ]
      },
      addAction: function( b, c, d, e ) {
        a.MixItUp.prototype._addHook( "_actions", b, c, d, e )
      },
      addFilter: function( b, c, d, e ) {
        a.MixItUp.prototype._addHook( "_filters", b, c, d, e )
      },
      _addHook: function( b, c, d, e, f ) {
        var g = a.MixItUp.prototype[ b ],
          h = {};
        f = 1 === f || "post" === f ? "post" : "pre", h[ c ] = {}, h[ c ][ f ] = {}, h[ c ][ f ][ d ] = e, a.extend( !0, g, h )
      },
      _init: function( b, c ) {
        var d = this;
        if ( d._execAction( "_init", 0, arguments ), c && a.extend( !0, d, c ), d._$body = a( "body" ), d._domNode = b, d._$container = a( b ), d._$container.addClass( d.layout.containerClass ), d._id = b.id, d._platformDetect(), d._brake = d._getPrefixedCSS( "transition", "none" ), d._refresh( !0 ), d._$parent = d._$targets.parent().length ? d._$targets.parent() : d._$container, d.load.sort && ( d._newSort = d._parseSort( d.load.sort ), d._newSortString = d.load.sort, d._activeSort = d.load.sort, d._sort(), d._printSort() ), d._activeFilter = "all" === d.load.filter ? d.selectors.target : "none" === d.load.filter ? "" : d.load.filter, d.controls.enable && d._bindHandlers(), d.controls.toggleFilterButtons ) {
          d._buildToggleArray();
          for ( var e = 0; e < d._toggleArray.length; e++ ) d._updateControls( {
            filter: d._toggleArray[ e ],
            sort: d._activeSort
          }, !0 )
        } else d.controls.enable && d._updateControls( {
          filter: d._activeFilter,
          sort: d._activeSort
        } );
        d._filter(), d._init = !0, d._$container.data( "mixItUp", d ), d._execAction( "_init", 1, arguments ), d._buildState(), d._$targets.css( d._brake ), d._goMix( d.animation.enable )
      },
      _platformDetect: function() {
        var a = this,
          c = [ "Webkit", "Moz", "O", "ms" ],
          d = [ "webkit", "moz" ],
          e = window.navigator.appVersion.match( /Chrome\/(\d+)\./ ) || !1,
          f = "undefined" != typeof InstallTrigger,
          g = function( a ) {
            for ( var b = 0; b < c.length; b++ )
              if ( c[ b ] + "Transition" in a.style ) return {
                prefix: "-" + c[ b ].toLowerCase() + "-",
                vendor: c[ b ]
              };
            return "transition" in a.style ? "" : !1
          },
          h = g( a._domNode );
        a._execAction( "_platformDetect", 0 ), a._chrome = e ? parseInt( e[ 1 ], 10 ) : !1, a._ff = f ? parseInt( window.navigator.userAgent.match( /rv:([^)]+)\)/ )[ 1 ] ) : !1, a._prefix = h.prefix, a._vendor = h.vendor, a._suckMode = window.atob && a._prefix ? !1 : !0, a._suckMode && ( a.animation.enable = !1 ), a._ff && a._ff <= 4 && ( a.animation.enable = !1 );
        for ( var i = 0; i < d.length && !window.requestAnimationFrame; i++ ) window.requestAnimationFrame = window[ d[ i ] + "RequestAnimationFrame" ];
        "function" != typeof Object.getPrototypeOf && ( "object" == typeof "test".__proto__ ? Object.getPrototypeOf = function( a ) {
          return a.__proto__
        } : Object.getPrototypeOf = function( a ) {
          return a.constructor.prototype
        } ), a._domNode.nextElementSibling === b && Object.defineProperty( Element.prototype, "nextElementSibling", {
          get: function() {
            for ( var a = this.nextSibling; a; ) {
              if ( 1 === a.nodeType ) return a;
              a = a.nextSibling
            }
            return null
          }
        } ), a._execAction( "_platformDetect", 1 )
      },
      _refresh: function( a, c ) {
        var d = this;
        d._execAction( "_refresh", 0, arguments ), d._$targets = d._$container.find( d.selectors.target );
        for ( var e = 0; e < d._$targets.length; e++ ) {
          var f = d._$targets[ e ];
          if ( f.dataset === b || c ) {
            f.dataset = {};
            for ( var g = 0; g < f.attributes.length; g++ ) {
              var h = f.attributes[ g ],
                i = h.name,
                j = h.value;
              if ( i.indexOf( "data-" ) > -1 ) {
                var k = d._helpers._camelCase( i.substring( 5, i.length ) );
                f.dataset[ k ] = j
              }
            }
          }
          f.mixParent === b && ( f.mixParent = d._id )
        }
        if ( d._$targets.length && a || !d._origOrder.length && d._$targets.length ) {
          d._origOrder = [];
          for ( var e = 0; e < d._$targets.length; e++ ) {
            var f = d._$targets[ e ];
            d._origOrder.push( f )
          }
        }
        d._execAction( "_refresh", 1, arguments )
      },
      _bindHandlers: function() {
        var c = this,
          d = a.MixItUp.prototype._bound._filter,
          e = a.MixItUp.prototype._bound._sort;
        c._execAction( "_bindHandlers", 0 ), c.controls.live ? c._$body.on( "click.mixItUp." + c._id, c.selectors.sort, function() {
          c._processClick( a( this ), "sort" )
        } ).on( "click.mixItUp." + c._id, c.selectors.filter, function() {
          c._processClick( a( this ), "filter" )
        } ) : ( c._$sortButtons = a( c.selectors.sort ), c._$filterButtons = a( c.selectors.filter ), c._$sortButtons.on( "click.mixItUp." + c._id, function() {
          c._processClick( a( this ), "sort" )
        } ), c._$filterButtons.on( "click.mixItUp." + c._id, function() {
          c._processClick( a( this ), "filter" )
        } ) ), d[ c.selectors.filter ] = d[ c.selectors.filter ] === b ? 1 : d[ c.selectors.filter ] + 1, e[ c.selectors.sort ] = e[ c.selectors.sort ] === b ? 1 : e[ c.selectors.sort ] + 1, c._execAction( "_bindHandlers", 1 )
      },
      _processClick: function( c, d ) {
        var e = this,
          f = function( c, d, f ) {
            var g = a.MixItUp.prototype;
            g._handled[ "_" + d ][ e.selectors[ d ] ] = g._handled[ "_" + d ][ e.selectors[ d ] ] === b ? 1 : g._handled[ "_" + d ][ e.selectors[ d ] ] + 1, g._handled[ "_" + d ][ e.selectors[ d ] ] === g._bound[ "_" + d ][ e.selectors[ d ] ] && ( c[ ( f ? "remove" : "add" ) + "Class" ]( e.controls.activeClass ), delete g._handled[ "_" + d ][ e.selectors[ d ] ] )
          };
        if ( e._execAction( "_processClick", 0, arguments ), !e._mixing || e.animation.queue && e._queue.length < e.animation.queueLimit ) {
          if ( e._clicking = !0, "sort" === d ) {
            var g = c.attr( "data-sort" );
            ( !c.hasClass( e.controls.activeClass ) || g.indexOf( "random" ) > -1 ) && ( a( e.selectors.sort ).removeClass( e.controls.activeClass ), f( c, d ), e.sort( g ) )
          }
          if ( "filter" === d ) {
            var h, i = c.attr( "data-filter" ),
              j = "or" === e.controls.toggleLogic ? "," : "";
            e.controls.toggleFilterButtons ? ( e._buildToggleArray(), c.hasClass( e.controls.activeClass ) ? ( f( c, d, !0 ), h = e._toggleArray.indexOf( i ), e._toggleArray.splice( h, 1 ) ) : ( f( c, d ), e._toggleArray.push( i ) ), e._toggleArray = a.grep( e._toggleArray, function( a ) {
              return a
            } ), e._toggleString = e._toggleArray.join( j ), e.filter( e._toggleString ) ) : c.hasClass( e.controls.activeClass ) || ( a( e.selectors.filter ).removeClass( e.controls.activeClass ), f( c, d ), e.filter( i ) )
          }
          e._execAction( "_processClick", 1, arguments )
        } else "function" == typeof e.callbacks.onMixBusy && e.callbacks.onMixBusy.call( e._domNode, e._state, e ), e._execAction( "_processClickBusy", 1, arguments )
      },
      _buildToggleArray: function() {
        var a = this,
          b = a._activeFilter.replace( /\s/g, "" );
        if ( a._execAction( "_buildToggleArray", 0, arguments ), "or" === a.controls.toggleLogic ) a._toggleArray = b.split( "," );
        else {
          a._toggleArray = b.split( "." ), !a._toggleArray[ 0 ] && a._toggleArray.shift();
          for ( var c, d = 0; c = a._toggleArray[ d ]; d++ ) a._toggleArray[ d ] = "." + c
        }
        a._execAction( "_buildToggleArray", 1, arguments )
      },
      _updateControls: function( c, d ) {
        var e = this,
          f = {
            filter: c.filter,
            sort: c.sort
          },
          g = function( a, b ) {
            try {
              d && "filter" === h && "none" !== f.filter && "" !== f.filter ? a.filter( b ).addClass( e.controls.activeClass ) : a.removeClass( e.controls.activeClass ).filter( b ).addClass( e.controls.activeClass )
            } catch ( c ) {}
          },
          h = "filter",
          i = null;
        e._execAction( "_updateControls", 0, arguments ), c.filter === b && ( f.filter = e._activeFilter ), c.sort === b && ( f.sort = e._activeSort ), f.filter === e.selectors.target && ( f.filter = "all" );
        for ( var j = 0; 2 > j; j++ ) i = e.controls.live ? a( e.selectors[ h ] ) : e[ "_$" + h + "Buttons" ], i && g( i, "[data-" + h + '="' + f[ h ] + '"]' ), h = "sort";
        e._execAction( "_updateControls", 1, arguments )
      },
      _filter: function() {
        var b = this;
        b._execAction( "_filter", 0 );
        for ( var c = 0; c < b._$targets.length; c++ ) {
          var d = a( b._$targets[ c ] );
          d.is( b._activeFilter ) ? b._$show = b._$show.add( d ) : b._$hide = b._$hide.add( d )
        }
        b._execAction( "_filter", 1 )
      },
      _sort: function() {
        var a = this,
          b = function( a ) {
            for ( var b = a.slice(), c = b.length, d = c; d--; ) {
              var e = parseInt( Math.random() * c ),
                f = b[ d ];
              b[ d ] = b[ e ], b[ e ] = f
            }
            return b
          };
        a._execAction( "_sort", 0 ), a._startOrder = [];
        for ( var c = 0; c < a._$targets.length; c++ ) {
          var d = a._$targets[ c ];
          a._startOrder.push( d )
        }
        switch ( a._newSort[ 0 ].sortBy ) {
          case "default":
            a._newOrder = a._origOrder;
            break;
          case "random":
            a._newOrder = b( a._startOrder );
            break;
          case "custom":
            a._newOrder = a._newSort[ 0 ].order;
            break;
          default:
            a._newOrder = a._startOrder.concat().sort( function( b, c ) {
              return a._compare( b, c )
            } )
        }
        a._execAction( "_sort", 1 )
      },
      _compare: function( a, b, c ) {
        c = c ? c : 0;
        var d = this,
          e = d._newSort[ c ].order,
          f = function( a ) {
            return a.dataset[ d._newSort[ c ].sortBy ] || 0
          },
          g = isNaN( 1 * f( a ) ) ? f( a ).toLowerCase() : 1 * f( a ),
          h = isNaN( 1 * f( b ) ) ? f( b ).toLowerCase() : 1 * f( b );
        return h > g ? "asc" === e ? -1 : 1 : g > h ? "asc" === e ? 1 : -1 : g === h && d._newSort.length > c + 1 ? d._compare( a, b, c + 1 ) : 0
      },
      _printSort: function( a ) {
        var b = this,
          c = a ? b._startOrder : b._newOrder,
          d = b._$parent[ 0 ].querySelectorAll( b.selectors.target ),
          e = d.length ? d[ d.length - 1 ].nextElementSibling : null,
          f = document.createDocumentFragment();
        b._execAction( "_printSort", 0, arguments );
        for ( var g = 0; g < d.length; g++ ) {
          var h = d[ g ],
            i = h.nextSibling;
          "absolute" !== h.style.position && ( i && "#text" === i.nodeName && b._$parent[ 0 ].removeChild( i ), b._$parent[ 0 ].removeChild( h ) )
        }
        for ( var g = 0; g < c.length; g++ ) {
          var j = c[ g ];
          if ( "default" !== b._newSort[ 0 ].sortBy || "desc" !== b._newSort[ 0 ].order || a ) f.appendChild( j ), f.appendChild( document.createTextNode( " " ) );
          else {
            var k = f.firstChild;
            f.insertBefore( j, k ), f.insertBefore( document.createTextNode( " " ), j )
          }
        }
        e ? b._$parent[ 0 ].insertBefore( f, e ) : b._$parent[ 0 ].appendChild( f ), b._execAction( "_printSort", 1, arguments )
      },
      _parseSort: function( a ) {
        for ( var b = this, c = "string" == typeof a ? a.split( " " ) : [ a ], d = [], e = 0; e < c.length; e++ ) {
          var f = "string" == typeof a ? c[ e ].split( ":" ) : [ "custom", c[ e ] ],
            g = {
              sortBy: b._helpers._camelCase( f[ 0 ] ),
              order: f[ 1 ] || "asc"
            };
          if ( d.push( g ), "default" === g.sortBy || "random" === g.sortBy ) break
        }
        return b._execFilter( "_parseSort", d, arguments )
      },
      _parseEffects: function() {
        var a = this,
          b = {
            opacity: "",
            transformIn: "",
            transformOut: "",
            filter: ""
          },
          c = function( b, c, d ) {
            if ( a.animation.effects.indexOf( b ) > -1 ) {
              if ( c ) {
                var e = a.animation.effects.indexOf( b + "(" );
                if ( e > -1 ) {
                  var f = a.animation.effects.substring( e ),
                    g = /\(([^)]+)\)/.exec( f ),
                    h = g[ 1 ];
                  return {
                    val: h
                  }
                }
              }
              return !0
            }
            return !1
          },
          d = function( a, b ) {
            return b ? "-" === a.charAt( 0 ) ? a.substr( 1, a.length ) : "-" + a : a
          },
          e = function( a, e ) {
            for ( var f = [
                [ "scale", ".01" ],
                [ "translateX", "20px" ],
                [ "translateY", "20px" ],
                [ "translateZ", "20px" ],
                [ "rotateX", "90deg" ],
                [ "rotateY", "90deg" ],
                [ "rotateZ", "180deg" ]
              ], g = 0; g < f.length; g++ ) {
              var h = f[ g ][ 0 ],
                i = f[ g ][ 1 ],
                j = e && "scale" !== h;
              b[ a ] += c( h ) ? h + "(" + d( c( h, !0 ).val || i, j ) + ") " : ""
            }
          };
        return b.opacity = c( "fade" ) ? c( "fade", !0 ).val || "0" : "1", e( "transformIn" ), a.animation.reverseOut ? e( "transformOut", !0 ) : b.transformOut = b.transformIn, b.transition = {}, b.transition = a._getPrefixedCSS( "transition", "all " + a.animation.duration + "ms " + a.animation.easing + ", opacity " + a.animation.duration + "ms linear" ), a.animation.stagger = c( "stagger" ) ? !0 : !1, a.animation.staggerDuration = parseInt( c( "stagger" ) && c( "stagger", !0 ).val ? c( "stagger", !0 ).val : 100 ), a._execFilter( "_parseEffects", b )
      },
      _buildState: function( a ) {
        var b = this,
          c = {};
        return b._execAction( "_buildState", 0 ), c = {
          activeFilter: "" === b._activeFilter ? "none" : b._activeFilter,
          activeSort: a && b._newSortString ? b._newSortString : b._activeSort,
          fail: !b._$show.length && "" !== b._activeFilter,
          $targets: b._$targets,
          $show: b._$show,
          $hide: b._$hide,
          totalTargets: b._$targets.length,
          totalShow: b._$show.length,
          totalHide: b._$hide.length,
          display: a && b._newDisplay ? b._newDisplay : b.layout.display
        }, a ? b._execFilter( "_buildState", c ) : ( b._state = c, void b._execAction( "_buildState", 1 ) )
      },
      _goMix: function( a ) {
        var b = this,
          c = function() {
            b._chrome && 31 === b._chrome && f( b._$parent[ 0 ] ), b._setInter(), d()
          },
          d = function() {
            var a = window.pageYOffset,
              c = window.pageXOffset;
            document.documentElement.scrollHeight;
            b._getInterMixData(), b._setFinal(), b._getFinalMixData(), window.pageYOffset !== a && window.scrollTo( c, a ), b._prepTargets(), window.requestAnimationFrame ? requestAnimationFrame( e ) : setTimeout( function() {
              e()
            }, 20 )
          },
          e = function() {
            b._animateTargets(), 0 === b._targetsBound && b._cleanUp()
          },
          f = function( a ) {
            var b = a.parentElement,
              c = document.createElement( "div" ),
              d = document.createDocumentFragment();
            b.insertBefore( c, a ), d.appendChild( a ), b.replaceChild( a, c )
          },
          g = b._buildState( !0 );
        b._execAction( "_goMix", 0, arguments ), !b.animation.duration && ( a = !1 ), b._mixing = !0, b._$container.removeClass( b.layout.containerClassFail ), "function" == typeof b.callbacks.onMixStart && b.callbacks.onMixStart.call( b._domNode, b._state, g, b ), b._$container.trigger( "mixStart", [ b._state, g, b ] ), b._getOrigMixData(), a && !b._suckMode ? window.requestAnimationFrame ? requestAnimationFrame( c ) : c() : b._cleanUp(), b._execAction( "_goMix", 1, arguments )
      },
      _getTargetData: function( a, b ) {
        var c, d = this;
        a.dataset[ b + "PosX" ] = a.offsetLeft, a.dataset[ b + "PosY" ] = a.offsetTop, d.animation.animateResizeTargets && ( c = d._suckMode ? {
          marginBottom: "",
          marginRight: ""
        } : window.getComputedStyle( a ), a.dataset[ b + "MarginBottom" ] = parseInt( c.marginBottom ), a.dataset[ b + "MarginRight" ] = parseInt( c.marginRight ), a.dataset[ b + "Width" ] = a.offsetWidth, a.dataset[ b + "Height" ] = a.offsetHeight )
      },
      _getOrigMixData: function() {
        var a = this,
          b = a._suckMode ? {
            boxSizing: ""
          } : window.getComputedStyle( a._$parent[ 0 ] ),
          c = b.boxSizing || b[ a._vendor + "BoxSizing" ];
        a._incPadding = "border-box" === c, a._execAction( "_getOrigMixData", 0 ), !a._suckMode && ( a.effects = a._parseEffects() ), a._$toHide = a._$hide.filter( ":visible" ), a._$toShow = a._$show.filter( ":hidden" ), a._$pre = a._$targets.filter( ":visible" ), a._startHeight = a._incPadding ? a._$parent.outerHeight() : a._$parent.height();
        for ( var d = 0; d < a._$pre.length; d++ ) {
          var e = a._$pre[ d ];
          a._getTargetData( e, "orig" )
        }
        a._execAction( "_getOrigMixData", 1 )
      },
      _setInter: function() {
        var a = this;
        a._execAction( "_setInter", 0 ), a._changingLayout && a.animation.animateChangeLayout ? ( a._$toShow.css( "display", a._newDisplay ), a._changingClass && a._$container.removeClass( a.layout.containerClass ).addClass( a._newClass ) ) : a._$toShow.css( "display", a.layout.display ), a._execAction( "_setInter", 1 )
      },
      _getInterMixData: function() {
        var a = this;
        a._execAction( "_getInterMixData", 0 );
        for ( var b = 0; b < a._$toShow.length; b++ ) {
          var c = a._$toShow[ b ];
          a._getTargetData( c, "inter" )
        }
        for ( var b = 0; b < a._$pre.length; b++ ) {
          var c = a._$pre[ b ];
          a._getTargetData( c, "inter" )
        }
        a._execAction( "_getInterMixData", 1 )
      },
      _setFinal: function() {
        var a = this;
        a._execAction( "_setFinal", 0 ), a._sorting && a._printSort(), a._$toHide.removeStyle( "display" ), a._changingLayout && a.animation.animateChangeLayout && a._$pre.css( "display", a._newDisplay ), a._execAction( "_setFinal", 1 )
      },
      _getFinalMixData: function() {
        var a = this;
        a._execAction( "_getFinalMixData", 0 );
        for ( var b = 0; b < a._$toShow.length; b++ ) {
          var c = a._$toShow[ b ];
          a._getTargetData( c, "final" )
        }
        for ( var b = 0; b < a._$pre.length; b++ ) {
          var c = a._$pre[ b ];
          a._getTargetData( c, "final" )
        }
        a._newHeight = a._incPadding ? a._$parent.outerHeight() : a._$parent.height(), a._sorting && a._printSort( !0 ), a._$toShow.removeStyle( "display" ), a._$pre.css( "display", a.layout.display ), a._changingClass && a.animation.animateChangeLayout && a._$container.removeClass( a._newClass ).addClass( a.layout.containerClass ), a._execAction( "_getFinalMixData", 1 )
      },
      _prepTargets: function() {
        var b = this,
          c = {
            _in: b._getPrefixedCSS( "transform", b.effects.transformIn ),
            _out: b._getPrefixedCSS( "transform", b.effects.transformOut )
          };
        b._execAction( "_prepTargets", 0 ), b.animation.animateResizeContainer && b._$parent.css( "height", b._startHeight + "px" );
        for ( var d = 0; d < b._$toShow.length; d++ ) {
          var e = b._$toShow[ d ],
            f = a( e );
          e.style.opacity = b.effects.opacity, e.style.display = b._changingLayout && b.animation.animateChangeLayout ? b._newDisplay : b.layout.display, f.css( c._in ), b.animation.animateResizeTargets && ( e.style.width = e.dataset.finalWidth + "px", e.style.height = e.dataset.finalHeight + "px", e.style.marginRight = -( e.dataset.finalWidth - e.dataset.interWidth ) + 1 * e.dataset.finalMarginRight + "px", e.style.marginBottom = -( e.dataset.finalHeight - e.dataset.interHeight ) + 1 * e.dataset.finalMarginBottom + "px" )
        }
        for ( var d = 0; d < b._$pre.length; d++ ) {
          var e = b._$pre[ d ],
            f = a( e ),
            g = {
              x: e.dataset.origPosX - e.dataset.interPosX,
              y: e.dataset.origPosY - e.dataset.interPosY
            },
            c = b._getPrefixedCSS( "transform", "translate(" + g.x + "px," + g.y + "px)" );
          f.css( c ), b.animation.animateResizeTargets && ( e.style.width = e.dataset.origWidth + "px", e.style.height = e.dataset.origHeight + "px", e.dataset.origWidth - e.dataset.finalWidth && ( e.style.marginRight = -( e.dataset.origWidth - e.dataset.interWidth ) + 1 * e.dataset.origMarginRight + "px" ), e.dataset.origHeight - e.dataset.finalHeight && ( e.style.marginBottom = -( e.dataset.origHeight - e.dataset.interHeight ) + 1 * e.dataset.origMarginBottom + "px" ) )
        }
        b._execAction( "_prepTargets", 1 )
      },
      _animateTargets: function() {
        var b = this;
        b._execAction( "_animateTargets", 0 ), b._targetsDone = 0, b._targetsBound = 0, b._$parent.css( b._getPrefixedCSS( "perspective", b.animation.perspectiveDistance + "px" ) ).css( b._getPrefixedCSS( "perspective-origin", b.animation.perspectiveOrigin ) ), b.animation.animateResizeContainer && b._$parent.css( b._getPrefixedCSS( "transition", "height " + b.animation.duration + "ms ease" ) ).css( "height", b._newHeight + "px" );
        for ( var c = 0; c < b._$toShow.length; c++ ) {
          var d = b._$toShow[ c ],
            e = a( d ),
            f = {
              x: d.dataset.finalPosX - d.dataset.interPosX,
              y: d.dataset.finalPosY - d.dataset.interPosY
            },
            g = b._getDelay( c ),
            h = {};
          d.style.opacity = "";
          for ( var i = 0; 2 > i; i++ ) {
            var j = 0 === i ? j = b._prefix : "";
            b._ff && b._ff <= 20 && ( h[ j + "transition-property" ] = "all", h[ j + "transition-timing-function" ] = b.animation.easing + "ms", h[ j + "transition-duration" ] = b.animation.duration + "ms" ), h[ j + "transition-delay" ] = g + "ms", h[ j + "transform" ] = "translate(" + f.x + "px," + f.y + "px)"
          }( b.effects.transform || b.effects.opacity ) && b._bindTargetDone( e ), b._ff && b._ff <= 20 ? e.css( h ) : e.css( b.effects.transition ).css( h )
        }
        for ( var c = 0; c < b._$pre.length; c++ ) {
          var d = b._$pre[ c ],
            e = a( d ),
            f = {
              x: d.dataset.finalPosX - d.dataset.interPosX,
              y: d.dataset.finalPosY - d.dataset.interPosY
            },
            g = b._getDelay( c );
          ( d.dataset.finalPosX !== d.dataset.origPosX || d.dataset.finalPosY !== d.dataset.origPosY ) && b._bindTargetDone( e ), e.css( b._getPrefixedCSS( "transition", "all " + b.animation.duration + "ms " + b.animation.easing + " " + g + "ms" ) ), e.css( b._getPrefixedCSS( "transform", "translate(" + f.x + "px," + f.y + "px)" ) ), b.animation.animateResizeTargets && ( d.dataset.origWidth - d.dataset.finalWidth && 1 * d.dataset.finalWidth && ( d.style.width = d.dataset.finalWidth + "px", d.style.marginRight = -( d.dataset.finalWidth - d.dataset.interWidth ) + 1 * d.dataset.finalMarginRight + "px" ), d.dataset.origHeight - d.dataset.finalHeight && 1 * d.dataset.finalHeight && ( d.style.height = d.dataset.finalHeight + "px", d.style.marginBottom = -( d.dataset.finalHeight - d.dataset.interHeight ) + 1 * d.dataset.finalMarginBottom + "px" ) )
        }
        b._changingClass && b._$container.removeClass( b.layout.containerClass ).addClass( b._newClass );
        for ( var c = 0; c < b._$toHide.length; c++ ) {
          for ( var d = b._$toHide[ c ], e = a( d ), g = b._getDelay( c ), k = {}, i = 0; 2 > i; i++ ) {
            var j = 0 === i ? j = b._prefix : "";
            k[ j + "transition-delay" ] = g + "ms", k[ j + "transform" ] = b.effects.transformOut, k.opacity = b.effects.opacity
          }
          e.css( b.effects.transition ).css( k ), ( b.effects.transform || b.effects.opacity ) && b._bindTargetDone( e )
        }
        b._execAction( "_animateTargets", 1 )
      },
      _bindTargetDone: function( b ) {
        var c = this,
          d = b[ 0 ];
        c._execAction( "_bindTargetDone", 0, arguments ), d.dataset.bound || ( d.dataset.bound = !0, c._targetsBound++, b.on( "webkitTransitionEnd.mixItUp transitionend.mixItUp", function( e ) {
          // sherlock 动画完成			
          ( e.originalEvent.propertyName.indexOf( "transform" ) > -1 || e.originalEvent.propertyName.indexOf( "opacity" ) > -1 ) && a( e.originalEvent.target ).is( c.selectors.target ) && ( b.off( ".mixItUp" ), delete d.dataset.bound, c._targetDone() )
        } ) ), c._execAction( "_bindTargetDone", 1, arguments )
      },
      _targetDone: function() {
        var a = this;
        a._execAction( "_targetDone", 0 ), a._targetsDone++, a._targetsDone === a._targetsBound && a._cleanUp(), a._execAction( "_targetDone", 1 )
      },
      _cleanUp: function() {
        var b = this,
          c = b.animation.animateResizeTargets ? "transform opacity width height margin-bottom margin-right" : "transform opacity";
        unBrake = function() {
          b._$targets.removeStyle( "transition", b._prefix )
        }, b._execAction( "_cleanUp", 0 ), b._changingLayout ? b._$show.css( "display", b._newDisplay ) : b._$show.css( "display", b.layout.display ), b._$targets.css( b._brake ), b._$targets.removeStyle( c, b._prefix ).removeAttr( "data-inter-pos-x data-inter-pos-y data-final-pos-x data-final-pos-y data-orig-pos-x data-orig-pos-y data-orig-height data-orig-width data-final-height data-final-width data-inter-width data-inter-height data-orig-margin-right data-orig-margin-bottom data-inter-margin-right data-inter-margin-bottom data-final-margin-right data-final-margin-bottom" ), b._$hide.removeStyle( "display" ), b._$parent.removeStyle( "height transition perspective-distance perspective perspective-origin-x perspective-origin-y perspective-origin perspectiveOrigin", b._prefix ), b._sorting && ( b._printSort(), b._activeSort = b._newSortString, b._sorting = !1 ), b._changingLayout && ( b._changingDisplay && ( b.layout.display = b._newDisplay, b._changingDisplay = !1 ), b._changingClass && ( b._$parent.removeClass( b.layout.containerClass ).addClass( b._newClass ), b.layout.containerClass = b._newClass, b._changingClass = !1 ), b._changingLayout = !1 ), b._refresh(), b._buildState(), b._state.fail && b._$container.addClass( b.layout.containerClassFail ), b._$show = a(), b._$hide = a(), window.requestAnimationFrame && requestAnimationFrame( unBrake ), b._mixing = !1, "function" == typeof b.callbacks._user && b.callbacks._user.call( b._domNode, b._state, b ), "function" == typeof b.callbacks.onMixEnd && b.callbacks.onMixEnd.call( b._domNode, b._state, b ), b._$container.trigger( "mixEnd", [ b._state, b ] ), b._state.fail && ( "function" == typeof b.callbacks.onMixFail && b.callbacks.onMixFail.call( b._domNode, b._state, b ), b._$container.trigger( "mixFail", [ b._state, b ] ) ), b._loading && ( "function" == typeof b.callbacks.onMixLoad && b.callbacks.onMixLoad.call( b._domNode, b._state, b ), b._$container.trigger( "mixLoad", [ b._state, b ] ) ), b._queue.length && ( b._execAction( "_queue", 0 ), b.multiMix( b._queue[ 0 ][ 0 ], b._queue[ 0 ][ 1 ], b._queue[ 0 ][ 2 ] ), b._queue.splice( 0, 1 ) ), b._execAction( "_cleanUp", 1 ), b._loading = !1
      },
      _getPrefixedCSS: function( a, b, c ) {
        var d = this,
          e = {},
          f = "",
          g = -1;
        for ( g = 0; 2 > g; g++ ) f = 0 === g ? d._prefix : "", c ? e[ f + a ] = f + b : e[ f + a ] = b;
        return d._execFilter( "_getPrefixedCSS", e, arguments )
      },
      _getDelay: function( a ) {
        var b = this,
          c = "function" == typeof b.animation.staggerSequence ? b.animation.staggerSequence.call( b._domNode, a, b._state ) : a,
          d = b.animation.stagger ? c * b.animation.staggerDuration : 0;
        return b._execFilter( "_getDelay", d, arguments )
      },
      _parseMultiMixArgs: function( a ) {
        for ( var b = this, c = {
            command: null,
            animate: b.animation.enable,
            callback: null
          }, d = 0; d < a.length; d++ ) {
          var e = a[ d ];
          null !== e && ( "object" == typeof e || "string" == typeof e ? c.command = e : "boolean" == typeof e ? c.animate = e : "function" == typeof e && ( c.callback = e ) )
        }
        return b._execFilter( "_parseMultiMixArgs", c, arguments )
      },
      _parseInsertArgs: function( b ) {
        for ( var c = this, d = {
            index: 0,
            $object: a(),
            multiMix: {
              filter: c._state.activeFilter
            },
            callback: null
          }, e = 0; e < b.length; e++ ) {
          var f = b[ e ];
          "number" == typeof f ? d.index = f : "object" == typeof f && f instanceof a ? d.$object = f : "object" == typeof f && c._helpers._isElement( f ) ? d.$object = a( f ) : "object" == typeof f && null !== f ? d.multiMix = f : "boolean" != typeof f || f ? "function" == typeof f && ( d.callback = f ) : d.multiMix = !1
        }
        return c._execFilter( "_parseInsertArgs", d, arguments )
      },
      _execAction: function( a, b, c ) {
        var d = this,
          e = b ? "post" : "pre";
        if ( !d._actions.isEmptyObject && d._actions.hasOwnProperty( a ) )
          for ( var f in d._actions[ a ][ e ] ) d._actions[ a ][ e ][ f ].call( d, c )
      },
      _execFilter: function( a, b, c ) {
        var d = this;
        if ( d._filters.isEmptyObject || !d._filters.hasOwnProperty( a ) ) return b;
        for ( var e in d._filters[ a ] ) return d._filters[ a ][ e ].call( d, c )
      },
      _helpers: {
        _camelCase: function( a ) {
          return a.replace( /-([a-z])/g, function( a ) {
            return a[ 1 ].toUpperCase()
          } )
        },
        _isElement: function( a ) {
          return window.HTMLElement ? a instanceof HTMLElement : null !== a && 1 === a.nodeType && "string" === a.nodeName
        }
      },
      isMixing: function() {
        var a = this;
        return a._execFilter( "isMixing", a._mixing )
      },
      filter: function() {
        var a = this,
          b = a._parseMultiMixArgs( arguments );
        a._clicking && ( a._toggleString = "" ), a.multiMix( {
          filter: b.command
        }, b.animate, b.callback )
      },
      sort: function() {
        var a = this,
          b = a._parseMultiMixArgs( arguments );
        a.multiMix( {
          sort: b.command
        }, b.animate, b.callback )
      },
      changeLayout: function() {
        var a = this,
          b = a._parseMultiMixArgs( arguments );
        a.multiMix( {
          changeLayout: b.command
        }, b.animate, b.callback )
      },
      multiMix: function() {
        var a = this,
          c = a._parseMultiMixArgs( arguments );
        if ( a._execAction( "multiMix", 0, arguments ), a._mixing ) a.animation.queue && a._queue.length < a.animation.queueLimit ? ( a._queue.push( arguments ), a.controls.enable && !a._clicking && a._updateControls( c.command ), a._execAction( "multiMixQueue", 1, arguments ) ) : ( "function" == typeof a.callbacks.onMixBusy && a.callbacks.onMixBusy.call( a._domNode, a._state, a ), a._$container.trigger( "mixBusy", [ a._state, a ] ), a._execAction( "multiMixBusy", 1, arguments ) );
        else {
          a.controls.enable && !a._clicking && ( a.controls.toggleFilterButtons && a._buildToggleArray(), a._updateControls( c.command, a.controls.toggleFilterButtons ) ), a._queue.length < 2 && ( a._clicking = !1 ), delete a.callbacks._user, c.callback && ( a.callbacks._user = c.callback );
          var d = c.command.sort,
            e = c.command.filter,
            f = c.command.changeLayout;
          a._refresh(), d && ( a._newSort = a._parseSort( d ), a._newSortString = d, a._sorting = !0, a._sort() ), e !== b && ( e = "all" === e ? a.selectors.target : e, a._activeFilter = e ), a._filter(), f && ( a._newDisplay = "string" == typeof f ? f : f.display || a.layout.display, a._newClass = f.containerClass || "", ( a._newDisplay !== a.layout.display || a._newClass !== a.layout.containerClass ) && ( a._changingLayout = !0, a._changingClass = a._newClass !== a.layout.containerClass, a._changingDisplay = a._newDisplay !== a.layout.display ) ), a._$targets.css( a._brake ), a._goMix( c.animate ^ a.animation.enable ? c.animate : a.animation.enable ), a._execAction( "multiMix", 1, arguments )
        }
      },
      insert: function() {
        var a = this,
          b = a._parseInsertArgs( arguments ),
          c = "function" == typeof b.callback ? b.callback : null,
          d = document.createDocumentFragment(),
          e = function() {
            return a._refresh(), a._$targets.length ? b.index < a._$targets.length || !a._$targets.length ? a._$targets[ b.index ] : a._$targets[ a._$targets.length - 1 ].nextElementSibling : a._$parent[ 0 ].children[ 0 ]
          }();
        if ( a._execAction( "insert", 0, arguments ), b.$object ) {
          for ( var f = 0; f < b.$object.length; f++ ) {
            var g = b.$object[ f ];
            d.appendChild( g ), d.appendChild( document.createTextNode( " " ) )
          }
          a._$parent[ 0 ].insertBefore( d, e )
        }
        a._execAction( "insert", 1, arguments ), "object" == typeof b.multiMix && a.multiMix( b.multiMix, c )
      },
      prepend: function() {
        var a = this,
          b = a._parseInsertArgs( arguments );
        a.insert( 0, b.$object, b.multiMix, b.callback )
      },
      append: function() {
        var a = this,
          b = a._parseInsertArgs( arguments );
        a.insert( a._state.totalTargets, b.$object, b.multiMix, b.callback )
      },
      getOption: function( a ) {
        var c = this,
          d = function( a, c ) {
            for ( var d = c.split( "." ), e = d.pop(), f = d.length, g = 1, h = d[ 0 ] || c;
              ( a = a[ h ] ) && f > g; ) h = d[ g ], g++;
            return a !== b ? a[ e ] !== b ? a[ e ] : a : void 0
          };
        return a ? c._execFilter( "getOption", d( c, a ), arguments ) : c
      },
      setOptions: function( b ) {
        var c = this;
        c._execAction( "setOptions", 0, arguments ), "object" == typeof b && a.extend( !0, c, b ), c._execAction( "setOptions", 1, arguments )
      },
      getState: function() {
        var a = this;
        return a._execFilter( "getState", a._state, a )
      },
      forceRefresh: function() {
        var a = this;
        a._refresh( !1, !0 )
      },
      destroy: function( b ) {
        var c = this,
          d = a.MixItUp.prototype._bound._filter,
          e = a.MixItUp.prototype._bound._sort;
        c._execAction( "destroy", 0, arguments ), c._$body.add( a( c.selectors.sort ) ).add( a( c.selectors.filter ) ).off( ".mixItUp" );
        for ( var f = 0; f < c._$targets.length; f++ ) {
          var g = c._$targets[ f ];
          b && ( g.style.display = "" ), delete g.mixParent
        }
        c._execAction( "destroy", 1, arguments ), d[ c.selectors.filter ] && d[ c.selectors.filter ] > 1 ? d[ c.selectors.filter ]-- : 1 === d[ c.selectors.filter ] && delete d[ c.selectors.filter ], e[ c.selectors.sort ] && e[ c.selectors.sort ] > 1 ? e[ c.selectors.sort ]-- : 1 === e[ c.selectors.sort ] && delete e[ c.selectors.sort ], delete a.MixItUp.prototype._instances[ c._id ]
      }
    }, a.fn.mixItUp = function() {
      var c, d = arguments,
        e = [],
        f = function( b, c ) {
          var d = new a.MixItUp,
            e = function() {
              return ( "00000" + ( 16777216 * Math.random() << 0 ).toString( 16 ) ).substr( -6 ).toUpperCase()
            };
          d._execAction( "_instantiate", 0, arguments ), b.id = b.id ? b.id : "MixItUp" + e(), d._instances[ b.id ] || ( d._instances[ b.id ] = d, d._init( b, c ) ), d._execAction( "_instantiate", 1, arguments )
        };
      return c = this.each( function() {
        if ( d && "string" == typeof d[ 0 ] ) {
          var c = a.MixItUp.prototype._instances[ this.id ];
          if ( "isLoaded" === d[ 0 ] ) e.push( c ? !0 : !1 );
          else {
            var g = c[ d[ 0 ] ]( d[ 1 ], d[ 2 ], d[ 3 ] );
            g !== b && e.push( g )
          }
        } else f( this, d[ 0 ] )
      } ), e.length ? e.length > 1 ? e : e[ 0 ] : c
    }, a.fn.removeStyle = function( c, d ) {
      return d = d ? d : "", this.each( function() {
        for ( var e = this, f = c.split( " " ), g = 0; g < f.length; g++ )
          for ( var h = 0; 4 > h; h++ ) {
            switch ( h ) {
              case 0:
                var i = f[ g ];
                break;
              case 1:
                var i = a.MixItUp.prototype._helpers._camelCase( i );
                break;
              case 2:
                var i = d + f[ g ];
                break;
              case 3:
                var i = a.MixItUp.prototype._helpers._camelCase( d + f[ g ] )
            }
            if ( e.style[ i ] !== b && "unknown" != typeof e.style[ i ] && e.style[ i ].length > 0 && ( e.style[ i ] = "" ), !d && 1 === h ) break
          }
        e.attributes && e.attributes.style && e.attributes.style !== b && "" === e.attributes.style.value && e.attributes.removeNamedItem( "style" )
      } )
    }
  }( jQuery );;


  //=====================colorPicker =============================
  ;
  ( function( window, undefined ) {
    "use strict"

    var _valueRanges = {
        rgb: {
          r: [ 0, 255 ],
          g: [ 0, 255 ],
          b: [ 0, 255 ]
        },
        hsv: {
          h: [ 0, 360 ],
          s: [ 0, 100 ],
          v: [ 0, 100 ]
        },
        hsl: {
          h: [ 0, 360 ],
          s: [ 0, 100 ],
          l: [ 0, 100 ]
        },
        cmy: {
          c: [ 0, 100 ],
          m: [ 0, 100 ],
          y: [ 0, 100 ]
        },
        cmyk: {
          c: [ 0, 100 ],
          m: [ 0, 100 ],
          y: [ 0, 100 ],
          k: [ 0, 100 ]
        },
        Lab: {
          L: [ 0, 100 ],
          a: [ -128, 127 ],
          b: [ -128, 127 ]
        },
        XYZ: {
          X: [ 0, 100 ],
          Y: [ 0, 100 ],
          Z: [ 0, 100 ]
        },
        alpha: {
          alpha: [ 0, 1 ]
        },
        HEX: {
          HEX: [ 0, 16777215 ]
        } // maybe we don't need this
      },

      _instance = {},
      _colors = {},

      // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html for more
      XYZMatrix = { // Observer = 2° (CIE 1931), Illuminant = D65
        X: [ 0.4124564, 0.3575761, 0.1804375 ],
        Y: [ 0.2126729, 0.7151522, 0.0721750 ],
        Z: [ 0.0193339, 0.1191920, 0.9503041 ],
        R: [ 3.2404542, -1.5371385, -0.4985314 ],
        G: [ -0.9692660, 1.8760108, 0.0415560 ],
        B: [ 0.0556434, -0.2040259, 1.0572252 ]
      },
      grey = {
        r: 0.298954,
        g: 0.586434,
        b: 0.114612
      }, // CIE-XYZ 1931
      luminance = {
        r: 0.2126,
        g: 0.7152,
        b: 0.0722
      }, // W3C 2.0

      _math = window.Math,
      _parseint = window.parseInt,

      Colors = window.Colors = function( options ) {
        this.colors = {
          RND: {}
        };
        this.options = {
          color: 'rgba(204, 82, 37, 0.8)', // init value(s)...
          XYZMatrix: XYZMatrix,
          // XYZReference: {},
          grey: grey,
          luminance: luminance,
          valueRanges: _valueRanges
            // customBG: '#808080'
            // convertCallback: undefined,
            // allMixDetails: false
        };
        initInstance( this, options ||  {} );
      },
      initInstance = function( THIS, options ) {
        var matrix,
          importColor,
          _options = THIS.options,
          customBG;

        focusInstance( THIS );
        for ( var option in options ) {
          if ( options[ option ] !== undefined ) _options[ option ] = options[ option ];
        }
        matrix = _options.XYZMatrix;
        if ( !options.XYZReference ) _options.XYZReference = {
          X: matrix.X[ 0 ] + matrix.X[ 1 ] + matrix.X[ 2 ],
          Y: matrix.Y[ 0 ] + matrix.Y[ 1 ] + matrix.Y[ 2 ],
          Z: matrix.Z[ 0 ] + matrix.Z[ 1 ] + matrix.Z[ 2 ]
        };
        customBG = _options.customBG;
        _options.customBG = ( typeof customBG === 'string' ) ? ColorConverter.txt2color( customBG ).rgb : customBG;
        _colors = setColor( THIS.colors, _options.color, undefined, true ); // THIS.colors = _colors =
      },
      focusInstance = function( THIS ) {
        if ( _instance !== THIS ) {
          _instance = THIS;
          _colors = THIS.colors;
        }
      };

    Colors.prototype.setColor = function( newCol, type, alpha ) {
      focusInstance( this );
      if ( newCol ) {
        return setColor( this.colors, newCol, type, undefined, alpha );
      } else {
        if ( alpha !== undefined ) {
          this.colors.alpha = limitValue( alpha, 0, 1 );
        }
        return convertColors( type );
      }
    };

    Colors.prototype.getColor = function( type ) {
      var result = this.colors,
        n = 0;

      if ( type ) {
        type = type.split( '.' );
        while ( result[ type[ n ] ] ) {
          result = result[ type[ n++ ] ];
        }
        if ( type.length !== n ) {
          result = undefined;
        }
      }
      return result;
    };

    Colors.prototype.setCustomBackground = function( col ) { // wild gues,... check again...
      focusInstance( this ); // needed???
      this.options.customBG = ( typeof col === 'string' ) ? ColorConverter.txt2color( col ).rgb : col;
      // return setColor(this.colors, this.options.customBG, 'rgb', true); // !!!!RGB
      return setColor( this.colors, undefined, 'rgb' ); // just recalculate existing
    };

    Colors.prototype.saveAsBackground = function() { // alpha
      focusInstance( this ); // needed???
      // return setColor(this.colors, this.colors.RND.rgb, 'rgb', true);
      return setColor( this.colors, undefined, 'rgb', true );
    };

    Colors.prototype.convertColor = function( color, type ) {
      var convert = ColorConverter,
        ranges = _valueRanges,
        types = type.split( '2' ),
        fromType = types[ 0 ],
        toType = types[ 1 ],
        test = /(?:RG|HS|CM|LA)/,
        normalizeFrom = test.test( fromType ),
        normalizeTo = test.test( toType ),
        exceptions = {
          LAB: 'Lab'
        },
        normalize = function( color, type, reverse ) {
          var result = {},
            Lab = type === 'Lab' ? 1 : 0;

          for ( var n in color ) { // faster (but bigger) way: if/else outside 2 for loops
            result[ n ] = reverse ?
              _math.round( color[ n ] * ( Lab || ranges[ type ][ n ][ 1 ] ) ) :
              color[ n ] / ( Lab || ranges[ type ][ n ][ 1 ] );
          }

          return result;
        };

      fromType = ranges[ fromType ] ? fromType : exceptions[ fromType ] || fromType.toLowerCase();
      toType = ranges[ toType ] ? toType : exceptions[ toType ] || toType.toLowerCase();

      if ( normalizeFrom && type !== 'RGB2HEX' ) { // from ABC to abc
        color = normalize( color, fromType );
      }
      color = fromType === toType ? color : ( // same type; returns same/normalized version
        convert[ fromType + '2' + toType ] ? convert[ fromType + '2' + toType ]( color, true ) : // existing converter
        toType === 'HEX' ? convert.RGB2HEX( type === 'RGB2HEX' ? color : normalize( fromType === 'rgb' ? color :
          convert[ fromType + '2rgb' ]( color, true ), 'rgb', true ) ) :
        convert[ 'rgb2' + toType ]( convert[ fromType + '2rgb' ]( color, true ), true ) // not in ColorConverter
      );
      if ( normalizeTo ) { // from abc to ABC
        color = normalize( color, toType, true );
      }

      return color;
    };

    Colors.prototype.toString = function( colorMode, forceAlpha ) {
      return ColorConverter.color2text( ( colorMode ||  'rgb' ).toLowerCase(), this.colors, forceAlpha );
    };


    // ------------------------------------------------------ //
    // ---------- Color calculation related stuff  ---------- //
    // -------------------------------------------------------//

    function setColor( colors, color, type, save, alpha ) { // color only full range
      if ( typeof color === 'string' ) {
        var color = ColorConverter.txt2color( color ); // new object
        type = color.type;
        _colors[ type ] = color[ type ];
        alpha = alpha !== undefined ? alpha : color.alpha;
      } else if ( color ) {
        for ( var n in color ) {
          colors[ type ][ n ] = type === 'Lab' ?
            limitValue( color[ n ], _valueRanges[ type ][ n ][ 0 ], _valueRanges[ type ][ n ][ 1 ] ) :
            limitValue( color[ n ] / _valueRanges[ type ][ n ][ 1 ], 0, 1 );
        }
      }
      if ( alpha !== undefined ) {
        colors.alpha = limitValue( +alpha, 0, 1 );
      }
      return convertColors( type, save ? colors : undefined );
    }

    function saveAsBackground( RGB, rgb, alpha ) {
      var grey = _instance.options.grey,
        color = {};

      color.RGB = {
        r: RGB.r,
        g: RGB.g,
        b: RGB.b
      };
      color.rgb = {
        r: rgb.r,
        g: rgb.g,
        b: rgb.b
      };
      color.alpha = alpha;
      // color.RGBLuminance = getLuminance(RGB);
      color.equivalentGrey = _math.round( grey.r * RGB.r + grey.g * RGB.g + grey.b * RGB.b );

      color.rgbaMixBlack = mixColors( rgb, {
        r: 0,
        g: 0,
        b: 0
      }, alpha, 1 );
      color.rgbaMixWhite = mixColors( rgb, {
        r: 1,
        g: 1,
        b: 1
      }, alpha, 1 );
      color.rgbaMixBlack.luminance = getLuminance( color.rgbaMixBlack, true );
      color.rgbaMixWhite.luminance = getLuminance( color.rgbaMixWhite, true );

      if ( _instance.options.customBG ) {
        color.rgbaMixCustom = mixColors( rgb, _instance.options.customBG, alpha, 1 );
        color.rgbaMixCustom.luminance = getLuminance( color.rgbaMixCustom, true );
        _instance.options.customBG.luminance = getLuminance( _instance.options.customBG, true );
      }

      return color;
    }

    function convertColors( type, colorObj ) {
      // console.time('convertColors');
      var _Math = _math,
        colors = colorObj || _colors,
        convert = ColorConverter,
        options = _instance.options,
        ranges = _valueRanges,
        RND = colors.RND,
        // type = colorType, // || _mode.type,
        modes, mode = '',
        from = '', // value = '',
        exceptions = {
          hsl: 'hsv',
          cmyk: 'cmy',
          rgb: type
        },
        RGB = RND.rgb,
        SAVE, SMART;

      if ( type !== 'alpha' ) {
        for ( var typ in ranges ) {
          if ( !ranges[ typ ][ typ ] ) { // no alpha|HEX
            if ( type !== typ && typ !== 'XYZ' ) {
              from = exceptions[ typ ] || 'rgb';
              colors[ typ ] = convert[ from + '2' + typ ]( colors[ from ] );
            }

            if ( !RND[ typ ] ) RND[ typ ] = {};
            modes = colors[ typ ];
            for ( mode in modes ) {
              RND[ typ ][ mode ] = _Math.round( modes[ mode ] * ( typ === 'Lab' ? 1 : ranges[ typ ][ mode ][ 1 ] ) );
            }
          }
        }
        if ( type !== 'Lab' ) {
          delete colors._rgb;
        }

        RGB = RND.rgb;
        colors.HEX = convert.RGB2HEX( RGB );
        colors.equivalentGrey =
          options.grey.r * colors.rgb.r +
          options.grey.g * colors.rgb.g +
          options.grey.b * colors.rgb.b;
        colors.webSave = SAVE = getClosestWebColor( RGB, 51 );
        // colors.webSave.HEX = convert.RGB2HEX(colors.webSave);
        colors.webSmart = SMART = getClosestWebColor( RGB, 17 );
        // colors.webSmart.HEX = convert.RGB2HEX(colors.webSmart);
        colors.saveColor =
          RGB.r === SAVE.r && RGB.g === SAVE.g && RGB.b === SAVE.b ? 'web save' :
          RGB.r === SMART.r && RGB.g === SMART.g && RGB.b === SMART.b ? 'web smart' : '';
        colors.hueRGB = convert.hue2RGB( colors.hsv.h );

        if ( colorObj ) {
          colors.background = saveAsBackground( RGB, colors.rgb, colors.alpha );
        }
      } // else RGB = RND.rgb;

      var rgb = colors.rgb, // for better minification...
        alpha = colors.alpha,
        luminance = 'luminance',
        background = colors.background,
        rgbaMixBlack, rgbaMixWhite, rgbaMixCustom,
        rgbaMixBG, rgbaMixBGMixBlack, rgbaMixBGMixWhite, rgbaMixBGMixCustom,
        _mixColors = mixColors,
        _getLuminance = getLuminance,
        _getWCAG2Ratio = getWCAG2Ratio,
        _getHueDelta = getHueDelta;

      rgbaMixBlack = _mixColors( rgb, {
        r: 0,
        g: 0,
        b: 0
      }, alpha, 1 );
      rgbaMixBlack[ luminance ] = _getLuminance( rgbaMixBlack, true );
      colors.rgbaMixBlack = rgbaMixBlack;

      rgbaMixWhite = _mixColors( rgb, {
        r: 1,
        g: 1,
        b: 1
      }, alpha, 1 );
      rgbaMixWhite[ luminance ] = _getLuminance( rgbaMixWhite, true );
      colors.rgbaMixWhite = rgbaMixWhite;

      if ( options.allMixDetails ) {
        rgbaMixBlack.WCAG2Ratio = _getWCAG2Ratio( rgbaMixBlack[ luminance ], 0 );
        rgbaMixWhite.WCAG2Ratio = _getWCAG2Ratio( rgbaMixWhite[ luminance ], 1 );

        if ( options.customBG ) {
          rgbaMixCustom = _mixColors( rgb, options.customBG, alpha, 1 );
          rgbaMixCustom[ luminance ] = _getLuminance( rgbaMixCustom, true );
          rgbaMixCustom.WCAG2Ratio = _getWCAG2Ratio( rgbaMixCustom[ luminance ], options.customBG[ luminance ] );
          colors.rgbaMixCustom = rgbaMixCustom;
        }

        rgbaMixBG = _mixColors( rgb, background.rgb, alpha, background.alpha );
        rgbaMixBG[ luminance ] = _getLuminance( rgbaMixBG, true ); // ?? do we need this?
        colors.rgbaMixBG = rgbaMixBG;

        rgbaMixBGMixBlack = _mixColors( rgb, background.rgbaMixBlack, alpha, 1 );
        rgbaMixBGMixBlack[ luminance ] = _getLuminance( rgbaMixBGMixBlack, true );
        rgbaMixBGMixBlack.WCAG2Ratio = _getWCAG2Ratio( rgbaMixBGMixBlack[ luminance ],
          background.rgbaMixBlack[ luminance ] );
        /* ------ */
        rgbaMixBGMixBlack.luminanceDelta = _Math.abs(
          rgbaMixBGMixBlack[ luminance ] - background.rgbaMixBlack[ luminance ] );
        rgbaMixBGMixBlack.hueDelta = _getHueDelta( background.rgbaMixBlack, rgbaMixBGMixBlack, true );
        /* ------ */
        colors.rgbaMixBGMixBlack = rgbaMixBGMixBlack;

        rgbaMixBGMixWhite = _mixColors( rgb, background.rgbaMixWhite, alpha, 1 );
        rgbaMixBGMixWhite[ luminance ] = _getLuminance( rgbaMixBGMixWhite, true );
        rgbaMixBGMixWhite.WCAG2Ratio = _getWCAG2Ratio( rgbaMixBGMixWhite[ luminance ],
          background.rgbaMixWhite[ luminance ] );
        /* ------ */
        rgbaMixBGMixWhite.luminanceDelta = _Math.abs(
          rgbaMixBGMixWhite[ luminance ] - background.rgbaMixWhite[ luminance ] );
        rgbaMixBGMixWhite.hueDelta = _getHueDelta( background.rgbaMixWhite, rgbaMixBGMixWhite, true );
        /* ------ */
        colors.rgbaMixBGMixWhite = rgbaMixBGMixWhite;
      }

      if ( options.customBG ) {
        rgbaMixBGMixCustom = _mixColors( rgb, background.rgbaMixCustom, alpha, 1 );
        rgbaMixBGMixCustom[ luminance ] = _getLuminance( rgbaMixBGMixCustom, true );
        rgbaMixBGMixCustom.WCAG2Ratio = _getWCAG2Ratio( rgbaMixBGMixCustom[ luminance ],
          background.rgbaMixCustom[ luminance ] );
        colors.rgbaMixBGMixCustom = rgbaMixBGMixCustom;
        /* ------ */
        rgbaMixBGMixCustom.luminanceDelta = _Math.abs(
          rgbaMixBGMixCustom[ luminance ] - background.rgbaMixCustom[ luminance ] );
        rgbaMixBGMixCustom.hueDelta = _getHueDelta( background.rgbaMixCustom, rgbaMixBGMixCustom, true );
        /* ------ */
      }

      colors.RGBLuminance = _getLuminance( RGB );
      colors.HUELuminance = _getLuminance( colors.hueRGB );

      // renderVars.readyToRender = true;
      if ( options.convertCallback ) {
        options.convertCallback( colors, type ); //, convert); //, _mode);
      }

      // console.timeEnd('convertColors')
      // if (colorObj)
      return colors;
    }


    // ------------------------------------------------------ //
    // ------------------ color conversion ------------------ //
    // -------------------------------------------------------//

    var ColorConverter = {
      txt2color: function( txt ) {
        var color = {},
          parts = txt.replace( /(?:#|\)|%)/g, '' ).split( '(' ),
          values = ( parts[ 1 ] || '' ).split( /,\s*/ ),
          type = parts[ 1 ] ? parts[ 0 ].substr( 0, 3 ) : 'rgb',
          m = '';

        color.type = type;
        color[ type ] = {};
        if ( parts[ 1 ] ) {
          for ( var n = 3; n--; ) {
            m = type[ n ] || type.charAt( n ); // IE7
            color[ type ][ m ] = +values[ n ] / _valueRanges[ type ][ m ][ 1 ];
          }
        } else {
          color.rgb = ColorConverter.HEX2rgb( parts[ 0 ] );
        }
        // color.color = color[type];
        color.alpha = values[ 3 ] ? +values[ 3 ] : 1;

        return color;
      },

      color2text: function( colorMode, colors, forceAlpha ) {
        var alpha = forceAlpha !== false && _math.round( colors.alpha * 100 ) / 100,
          hasAlpha = typeof alpha === 'number' &&
          forceAlpha !== false && ( forceAlpha ||  alpha !== 1 ),
          RGB = colors.RND.rgb,
          HSL = colors.RND.hsl,
          shouldBeHex = colorMode === 'hex' && hasAlpha,
          isHex = colorMode === 'hex' && !shouldBeHex,
          isRgb = colorMode === 'rgb' ||  shouldBeHex,
          innerText = isRgb ? RGB.r + ', ' + RGB.g + ', ' + RGB.b :
          !isHex ? HSL.h + ', ' + HSL.s + '%, ' + HSL.l + '%' :
          '#' + colors.HEX;

        return isHex ? innerText : ( shouldBeHex ? 'rgb' : colorMode ) +
          ( hasAlpha ? 'a' : '' ) + '(' + innerText + ( hasAlpha ? ', ' + alpha : '' ) + ')';
      },

      RGB2HEX: function( RGB ) {
        return (
          ( RGB.r < 16 ? '0' : '' ) + RGB.r.toString( 16 ) +
          ( RGB.g < 16 ? '0' : '' ) + RGB.g.toString( 16 ) +
          ( RGB.b < 16 ? '0' : '' ) + RGB.b.toString( 16 )
        ).toUpperCase();
      },

      HEX2rgb: function( HEX ) {
        HEX = HEX.split( '' ); // IE7
        return {
          r: +( '0x' + HEX[ 0 ] + HEX[ HEX[ 3 ] ? 1 : 0 ] ) / 255,
          g: +( '0x' + HEX[ HEX[ 3 ] ? 2 : 1 ] + ( HEX[ 3 ] || HEX[ 1 ] ) ) / 255,
          b: +( '0x' + ( HEX[ 4 ] || HEX[ 2 ] ) + ( HEX[ 5 ] || HEX[ 2 ] ) ) / 255
        };
      },

      hue2RGB: function( hue ) {
        var _Math = _math,
          h = hue * 6,
          mod = ~~h % 6, // Math.floor(h) -> faster in most browsers
          i = h === 6 ? 0 : ( h - mod );

        return {
          r: _Math.round( [ 1, 1 - i, 0, 0, i, 1 ][ mod ] * 255 ),
          g: _Math.round( [ i, 1, 1, 1 - i, 0, 0 ][ mod ] * 255 ),
          b: _Math.round( [ 0, 0, i, 1, 1, 1 - i ][ mod ] * 255 )
        };
      },

      // ------------------------ HSV ------------------------ //

      rgb2hsv: function( rgb ) { // faster
        var _Math = _math,
          r = rgb.r,
          g = rgb.g,
          b = rgb.b,
          k = 0,
          chroma, min, s;

        if ( g < b ) {
          g = b + ( b = g, 0 );
          k = -1;
        }
        min = b;
        if ( r < g ) {
          r = g + ( g = r, 0 );
          k = -2 / 6 - k;
          min = _Math.min( g, b ); // g < b ? g : b; ???
        }
        chroma = r - min;
        s = r ? ( chroma / r ) : 0;
        return {
          h: s < 1e-15 ? ( ( _colors && _colors.hsl && _colors.hsl.h ) || 0 ) : chroma ? _Math.abs( k + ( g - b ) / ( 6 * chroma ) ) : 0,
          s: r ? ( chroma / r ) : ( ( _colors && _colors.hsv && _colors.hsv.s ) || 0 ), // ??_colors.hsv.s || 0
          v: r
        };
      },

      hsv2rgb: function( hsv ) {
        var h = hsv.h * 6,
          s = hsv.s,
          v = hsv.v,
          i = ~~h, // Math.floor(h) -> faster in most browsers
          f = h - i,
          p = v * ( 1 - s ),
          q = v * ( 1 - f * s ),
          t = v * ( 1 - ( 1 - f ) * s ),
          mod = i % 6;

        return {
          r: [ v, q, p, p, t, v ][ mod ],
          g: [ t, v, v, q, p, p ][ mod ],
          b: [ p, p, t, v, v, q ][ mod ]
        };
      },

      // ------------------------ HSL ------------------------ //

      hsv2hsl: function( hsv ) {
        var l = ( 2 - hsv.s ) * hsv.v,
          s = hsv.s * hsv.v;

        s = !hsv.s ? 0 : l < 1 ? ( l ? s / l : 0 ) : s / ( 2 - l );

        return {
          h: hsv.h,
          s: !hsv.v && !s ? ( ( _colors && _colors.hsl && _colors.hsl.s ) || 0 ) : s, // ???
          l: l / 2
        };
      },

      rgb2hsl: function( rgb, dependent ) { // not used in Color
        var hsv = ColorConverter.rgb2hsv( rgb );

        return ColorConverter.hsv2hsl( dependent ? hsv : ( _colors.hsv = hsv ) );
      },

      hsl2rgb: function( hsl ) {
        var h = hsl.h * 6,
          s = hsl.s,
          l = hsl.l,
          v = l < 0.5 ? l * ( 1 + s ) : ( l + s ) - ( s * l ),
          m = l + l - v,
          sv = v ? ( ( v - m ) / v ) : 0,
          sextant = ~~h, // Math.floor(h) -> faster in most browsers
          fract = h - sextant,
          vsf = v * sv * fract,
          t = m + vsf,
          q = v - vsf,
          mod = sextant % 6;

        return {
          r: [ v, q, m, m, t, v ][ mod ],
          g: [ t, v, v, q, m, m ][ mod ],
          b: [ m, m, t, v, v, q ][ mod ]
        };
      },

      // ------------------------ CMYK ------------------------ //
      // Quote from Wikipedia:
      // "Since RGB and CMYK spaces are both device-dependent spaces, there is no
      // simple or general conversion formula that converts between them.
      // Conversions are generally done through color management systems, using
      // color profiles that describe the spaces being converted. Nevertheless, the
      // conversions cannot be exact, since these spaces have very different gamuts."
      // Translation: the following are just simple RGB to CMY(K) and visa versa conversion functions.

      rgb2cmy: function( rgb ) {
        return {
          c: 1 - rgb.r,
          m: 1 - rgb.g,
          y: 1 - rgb.b
        };
      },

      cmy2cmyk: function( cmy ) {
        var _Math = _math,
          k = _Math.min( _Math.min( cmy.c, cmy.m ), cmy.y ),
          t = 1 - k || 1e-20;

        return { // regular
          c: ( cmy.c - k ) / t,
          m: ( cmy.m - k ) / t,
          y: ( cmy.y - k ) / t,
          k: k
        };
      },

      cmyk2cmy: function( cmyk ) {
        var k = cmyk.k;

        return { // regular
          c: cmyk.c * ( 1 - k ) + k,
          m: cmyk.m * ( 1 - k ) + k,
          y: cmyk.y * ( 1 - k ) + k
        };
      },

      cmy2rgb: function( cmy ) {
        return {
          r: 1 - cmy.c,
          g: 1 - cmy.m,
          b: 1 - cmy.y
        };
      },

      rgb2cmyk: function( rgb, dependent ) {
        var cmy = ColorConverter.rgb2cmy( rgb ); // doppelt??

        return ColorConverter.cmy2cmyk( dependent ? cmy : ( _colors.cmy = cmy ) );
      },

      cmyk2rgb: function( cmyk, dependent ) {
        var cmy = ColorConverter.cmyk2cmy( cmyk ); // doppelt??

        return ColorConverter.cmy2rgb( dependent ? cmy : ( _colors.cmy = cmy ) );
      },

      // ------------------------ LAB ------------------------ //

      XYZ2rgb: function( XYZ, skip ) {
        var _Math = _math,
          M = _instance.options.XYZMatrix,
          X = XYZ.X,
          Y = XYZ.Y,
          Z = XYZ.Z,
          r = X * M.R[ 0 ] + Y * M.R[ 1 ] + Z * M.R[ 2 ],
          g = X * M.G[ 0 ] + Y * M.G[ 1 ] + Z * M.G[ 2 ],
          b = X * M.B[ 0 ] + Y * M.B[ 1 ] + Z * M.B[ 2 ],
          N = 1 / 2.4;

        M = 0.0031308;

        r = ( r > M ? 1.055 * _Math.pow( r, N ) - 0.055 : 12.92 * r );
        g = ( g > M ? 1.055 * _Math.pow( g, N ) - 0.055 : 12.92 * g );
        b = ( b > M ? 1.055 * _Math.pow( b, N ) - 0.055 : 12.92 * b );

        if ( !skip ) { // out of gammut
          _colors._rgb = {
            r: r,
            g: g,
            b: b
          };
        }

        return {
          r: limitValue( r, 0, 1 ),
          g: limitValue( g, 0, 1 ),
          b: limitValue( b, 0, 1 )
        };
      },

      rgb2XYZ: function( rgb ) {
        var _Math = _math,
          M = _instance.options.XYZMatrix,
          r = rgb.r,
          g = rgb.g,
          b = rgb.b,
          N = 0.04045;

        r = ( r > N ? _Math.pow( ( r + 0.055 ) / 1.055, 2.4 ) : r / 12.92 );
        g = ( g > N ? _Math.pow( ( g + 0.055 ) / 1.055, 2.4 ) : g / 12.92 );
        b = ( b > N ? _Math.pow( ( b + 0.055 ) / 1.055, 2.4 ) : b / 12.92 );

        return {
          X: r * M.X[ 0 ] + g * M.X[ 1 ] + b * M.X[ 2 ],
          Y: r * M.Y[ 0 ] + g * M.Y[ 1 ] + b * M.Y[ 2 ],
          Z: r * M.Z[ 0 ] + g * M.Z[ 1 ] + b * M.Z[ 2 ]
        };
      },

      XYZ2Lab: function( XYZ ) {
        var _Math = _math,
          R = _instance.options.XYZReference,
          X = XYZ.X / R.X,
          Y = XYZ.Y / R.Y,
          Z = XYZ.Z / R.Z,
          N = 16 / 116,
          M = 1 / 3,
          K = 0.008856,
          L = 7.787037;

        X = X > K ? _Math.pow( X, M ) : ( L * X ) + N;
        Y = Y > K ? _Math.pow( Y, M ) : ( L * Y ) + N;
        Z = Z > K ? _Math.pow( Z, M ) : ( L * Z ) + N;

        return {
          L: ( 116 * Y ) - 16,
          a: 500 * ( X - Y ),
          b: 200 * ( Y - Z )
        };
      },

      Lab2XYZ: function( Lab ) {
        var _Math = _math,
          R = _instance.options.XYZReference,
          Y = ( Lab.L + 16 ) / 116,
          X = Lab.a / 500 + Y,
          Z = Y - Lab.b / 200,
          X3 = _Math.pow( X, 3 ),
          Y3 = _Math.pow( Y, 3 ),
          Z3 = _Math.pow( Z, 3 ),
          N = 16 / 116,
          K = 0.008856,
          L = 7.787037;

        return {
          X: ( X3 > K ? X3 : ( X - N ) / L ) * R.X,
          Y: ( Y3 > K ? Y3 : ( Y - N ) / L ) * R.Y,
          Z: ( Z3 > K ? Z3 : ( Z - N ) / L ) * R.Z
        };
      },

      rgb2Lab: function( rgb, dependent ) {
        var XYZ = ColorConverter.rgb2XYZ( rgb );

        return ColorConverter.XYZ2Lab( dependent ? XYZ : ( _colors.XYZ = XYZ ) );
      },

      Lab2rgb: function( Lab, dependent ) {
        var XYZ = ColorConverter.Lab2XYZ( Lab );

        return ColorConverter.XYZ2rgb( dependent ? XYZ : ( _colors.XYZ = XYZ ), dependent );
      }
    };

    // ------------------------------------------------------ //
    // ------------------ helper functions ------------------ //
    // -------------------------------------------------------//

    function getClosestWebColor( RGB, val ) {
      var out = {},
        tmp = 0,
        half = val / 2;

      for ( var n in RGB ) {
        tmp = RGB[ n ] % val; // 51 = 'web save', 17 = 'web smart'
        out[ n ] = RGB[ n ] + ( tmp > half ? val - tmp : -tmp );
      }
      return out;
    }

    function getHueDelta( rgb1, rgb2, nominal ) {
      var _Math = _math;

      return ( _Math.max( rgb1.r - rgb2.r, rgb2.r - rgb1.r ) +
        _Math.max( rgb1.g - rgb2.g, rgb2.g - rgb1.g ) +
        _Math.max( rgb1.b - rgb2.b, rgb2.b - rgb1.b ) ) * ( nominal ? 255 : 1 ) / 765;
    }

    function getLuminance( rgb, normalized ) {
      var div = normalized ? 1 : 255,
        RGB = [ rgb.r / div, rgb.g / div, rgb.b / div ],
        luminance = _instance.options.luminance;

      for ( var i = RGB.length; i--; ) {
        RGB[ i ] = RGB[ i ] <= 0.03928 ? RGB[ i ] / 12.92 : _math.pow( ( ( RGB[ i ] + 0.055 ) / 1.055 ), 2.4 );
      }
      return ( ( luminance.r * RGB[ 0 ] ) + ( luminance.g * RGB[ 1 ] ) + ( luminance.b * RGB[ 2 ] ) );
    }

    function mixColors( topColor, bottomColor, topAlpha, bottomAlpha ) {
      var newColor = {},
        alphaTop = ( topAlpha !== undefined ? topAlpha : 1 ),
        alphaBottom = ( bottomAlpha !== undefined ? bottomAlpha : 1 ),
        alpha = alphaTop + alphaBottom * ( 1 - alphaTop ); // 1 - (1 - alphaTop) * (1 - alphaBottom);

      for ( var n in topColor ) {
        newColor[ n ] = ( topColor[ n ] * alphaTop + bottomColor[ n ] * alphaBottom * ( 1 - alphaTop ) ) / alpha;
      }
      newColor.a = alpha;
      return newColor;
    }

    function getWCAG2Ratio( lum1, lum2 ) {
      var ratio = 1;

      if ( lum1 >= lum2 ) {
        ratio = ( lum1 + 0.05 ) / ( lum2 + 0.05 );
      } else {
        ratio = ( lum2 + 0.05 ) / ( lum1 + 0.05 );
      }
      return _math.round( ratio * 100 ) / 100;
    }

    function limitValue( value, min, max ) {
      // return Math.max(min, Math.min(max, value)); // faster??
      return ( value > max ? max : value < min ? min : value );
    }
  } )( window );

  ;
  ( function( window, undefined ) {
    "use strict"

    // see colorPicker.html for the following encrypted variables... will only be used in buildView()
    var _html = ( '^§app alpha-bg-w">^§slds">^§sldl-1">$^§sldl-2">$^§sldl-3">$^§curm">$^§sldr-1">$^§sldr-2">$^§sldr-4">$^§curl">$^§curr">$$^§opacity">|^§opacity-slider">$$$^§memo">^§raster">$^§raster-bg">$|$|$|$|$|$|$|$|$^§memo-store">$^§memo-cursor">$$^§panel">^§hsv">^hsl-mode §ß">$^hsv-h-ß §ß">H$^hsv-h-~ §~">-^§nsarrow">$$^hsl-h-@ §@">H$^hsv-s-ß §ß">S$^hsv-s-~ §~">-$^hsl-s-@ §@">S$^hsv-v-ß §ß">B$^hsv-v-~ §~">-$^hsl-l-@ §@">L$$^§hsl §hide">^hsv-mode §ß">$^hsl-h-ß §ß">H$^hsl-h-~ §~">-$^hsv-h-@ §@">H$^hsl-s-ß §ß">S$^hsl-s-~ §~">-$^hsv-s-@ §@">S$^hsl-l-ß §ß">L$^hsl-l-~ §~">-$^hsv-v-@ §@">B$$^§rgb">^rgb-r-ß §ß">R$^rgb-r-~ §~">-$^rgb-r-@ §ß">&nbsp;$^rgb-g-ß §ß">G$^rgb-g-~ §~">-$^rgb-g-@ §ß">&nbsp;$^rgb-b-ß §ß">B$^rgb-b-~ §~">-$^rgb-b-@ §ß">&nbsp;$$^§cmyk">^Lab-mode §ß">$^cmyk-c-ß §@">C$^cmyk-c-~ §~">-$^Lab-L-@ §@">L$^cmyk-m-ß §@">M$^cmyk-m-~ §~">-$^Lab-a-@ §@">a$^cmyk-y-ß §@">Y$^cmyk-y-~ §~">-$^Lab-b-@ §@">b$^cmyk-k-ß §@">K$^cmyk-k-~ §~">-$^Lab-x-@ §ß">&nbsp;$$^§Lab §hide">^cmyk-mode §ß">$^Lab-L-ß §@">L$^Lab-L-~ §~">-$^cmyk-c-@ §@">C$^Lab-a-ß §@">a$^Lab-a-~ §~">-$^cmyk-m-@ §@">M$^Lab-b-ß §@">b$^Lab-b-~ §~">-$^cmyk-y-@ §@">Y$^Lab-x-ß §@">&nbsp;$^Lab-x-~ §~">-$^cmyk-k-@ §@">K$$^§alpha">^alpha-ß §ß">A$^alpha-~ §~">-$^alpha-@ §ß">W$$^§HEX">^HEX-ß §ß">#$^HEX-~ §~">-$^HEX-@ §ß">M$$^§ctrl">^§raster">$^§cont">$^§cold">$^§col1">|&nbsp;$$^§col2">|&nbsp;$$^§bres">RESET$^§bsav">SAVE$$$^§exit">$^§resize">$^§resizer">|$$$' ).
    replace( /\^/g, '<div class="' ).replace( /\$/g, '</div>' ).replace( /~/g, 'disp' ).replace( /ß/g, 'butt' ).replace( /@/g, 'labl' ).replace( /\|/g, '<div>' ),
      _cssFunc = ( 'är^1,äg^1,äb^1,öh^1,öh?1,öh?2,ös?1,öv?1,üh^1,üh?1,üh?2,üs?1,ül?1,.no-rgb-r är?2,.no-rgb-r är?3,.no-rgb-r är?4,.no-rgb-g äg?2,.no-rgb-g äg?3,.no-rgb-g äg?4,.no-rgb-b äb?2,.no-rgb-b äb?3,.no-rgb-b äb?4{visibility:hidden}är^2,är^3,äg^2,äg^3,äb^2,äb^3{@-image:url(_patches.png)}.§slds div{@-image:url(_vertical.png)}öh^2,ös^1,öv^1,üh^2,üs^1,ül^1{@-image:url(_horizontal.png)}ös?4,öv^3,üs?4,ül^3{@:#000}üs?3,ül^4{@:#fff}är?1{@-color:#f00}äg?1{@-color:#0f0}äb?1{@-color:#00f}är^2{@|-1664px 0}är^3{@|-896px 0}är?1,äg?1,äb?1,öh^3,ös^2,öv?2Ü-2432Öär?2Ü-2944Öär?3Ü-4480Öär?4Ü-3202Öäg^2Äöh^2{@|-640px 0}äg^3{@|-384px 0}äg?2Ü-4736Öäg?3Ü-3968Öäg?4Ü-3712Öäb^2{@|-1152px 0}äb^3{@|-1408px 0}äb?2Ü-3456Öäb?3Ü-4224Öäb?4Ü-2688Ööh^2Äär^3Ääb?4Ü0}öh?4,üh?4Ü-1664Öös^1,öv^1,üs^1,ül^1Ääg^3{@|-256px 0}ös^3,öv?4,üs^3,ül?4Ü-2176Öös?2,öv^2Ü-1920Öüh^2{@|-768px 0}üh^3,üs^2,ül?2Ü-5184Öüs?2,ül^2Ü-5824Ö.S är^2{@|-128px -128Ö.S är?1Ääg?1Ääb?1Äöh^3Äös^2Äöv?2Ü-1408Ö.S är?2Ääb^3Ü-128Ö.S är?3Ü-896Ö.S är?4Ü-256Ö.S äg^2{@|-256px -128Ö.S äg?2Ü-1024Ö.S äg?3Ü-640Ö.S äg?4Ü-512Ö.S äb^2{@|-128px 0}.S äb?2Ü-384Ö.S äb?3Ü-768Ö.S öh?4Äüh?4Ü-1536Ö.S ös^1Äöv^1Äüs^1Äül^1{@|-512px 0}.S ös^3Äöv?4Äüs^3Äül?4Ü-1280Ö.S ös?2Äöv^2Ü-1152Ö.S üh^2{@|-1024px 0}.S üh^3Äüs^2Äül?2Ü-5440Ö.S üs?2Äül^2Ü-5696Ö.XXS ös^2,.XXS öv?2Ü-5120Ö.XXS ös^3,.XXS öv?4,.XXS üs^3,.XXS ül^3,.XXS ül?4Ü-5056Ö.XXS ös?2,.XXS öv^2Ü-4992Ö.XXS üs^2,.XXS ül?2Ü-5568Ö.XXS üs?2,.XXS ül^2Ü-5632Ö' ).
    replace( /Ü/g, '{@|0 ' ).replace( /Ö/g, 'px}' ).replace( /Ä/g, ',.S ' ).replace( /\|/g, '-position:' ).replace( /@/g, 'background' ).replace( /ü/g, '.hsl-' ).replace( /ö/g, '.hsv-' ).replace( /ä/g, '.rgb-' ).replace( /~/g, ' .no-rgb-}' ).replace( /\?/g, ' .§sldr-' ).replace( /\^/g, ' .§sldl-' ),
      _cssMain = ( '∑{@#bbb;font-family:monospace, "Courier New", Courier, mono;font-size:12¥line-ä15¥font-weight:bold;cursor:default;~412¥ä323¥?top-left-radius:7¥?top-Ü-radius:7¥?bottom-Ü-radius:7¥?bottom-left-radius:7¥ö@#444}.S{~266¥ä177px}.XS{~158¥ä173px}.XXS{ä105¥~154px}.no-alpha{ä308px}.no-alpha .§opacity,.no-alpha .§alpha{display:none}.S.no-alpha{ä162px}.XS.no-alpha{ä158px}.XXS.no-alpha{ä90px}∑,∑ div{border:none;padding:0¥float:none;margin:0¥outline:none;box-sizing:content-box}∑ div{|absolute}^s .§curm,«§disp,«§nsarrow,∑ .§exit,∑ ø-cursor,∑ .§resize{öimage:url(_icons.png)}∑ .do-drag div{cursor:none}∑ .§opacity,ø .§raster-bg,∑ .§raster{öimage:url(_bgs.png)}∑ ^s{~287¥ä256¥top:10¥left:10¥overflow:hidden;cursor:crosshair}.S ^s{~143¥ä128¥left:9¥top:9px}.XS ^s{left:7¥top:7px}.XXS ^s{left:5¥top:5px}^s div{~256¥ä256¥left:0px}.S ^l-1,.S ^l-2,.S ^l-3,.S ^l-4{~128¥ä128px}.XXS ^s,.XXS ^s ^l-1,.XXS ^s ^l-2,.XXS ^s ^l-3,.XXS ^s ^l-4{ä64px}^s ^r-1,^s ^r-2,^s ^r-3,^s ^r-4{~31¥left:256¥cursor:default}.S ^r-1,.S ^r-2,.S ^r-3,.S ^r-4{~15¥ä128¥left:128px}^s .§curm{margin:-5¥~11¥ä11¥ö|-36px -30px}.light .§curm{ö|-7px -30px}^s .§curl,^s .§curr{~0¥ä0¥margin:-3px -4¥border:4px solid;cursor:default;left:auto;öimage:none}^s .§curl,∑ ^s .§curl-dark,.hue-dark div.§curl{Ü:27¥?@† † † #fff}.light .§curl,∑ ^s .§curl-light,.hue-light .§curl{?@† † † #000}.S ^s .§curl,.S ^s .§curr{?~3px}.S ^s .§curl-light,.S ^s .§curl{Ü:13px}^s .§curr,∑ ^s .§curr-dark{Ü:4¥?@† #fff † †}.light .§curr,∑ ^s .§curr-light{?@† #000 † †}∑ .§opacity{bottom:44¥left:10¥ä10¥~287¥ö|0 -87px}.S .§opacity{bottom:27¥left:9¥~143¥ö|0 -100px}.XS .§opacity{left:7¥bottom:25px}.XXS .§opacity{left:5¥bottom:23px}.§opacity div{~100%;ä16¥margin-top:-3¥overflow:hidden}.§opacity .§opacity-slider{margin:0 -4¥~0¥ä8¥?~4¥?style:solid;?@#eee †}∑ ø{bottom:10¥left:10¥~288¥ä31¥ö@#fff}.S ø{ä15¥~144¥left:9¥bottom:9px}.XS ø{left:7¥bottom:7px}.XXS ø{left:5¥bottom:5px}ø div{|relative;float:left;~31¥ä31¥margin-Ü:1px}.S ø div{~15¥ä15px}∑ .§raster,ø .§raster-bg,.S ø .§raster,.S ø .§raster-bg{|absolute;top:0¥Ü:0¥bottom:0¥left:0¥~100%}.S ø .§raster-bg{ö|0 -31px}∑ .§raster{opacity:0.2;ö|0 -49px}.alpha-bg-b ø{ö@#333}.alpha-bg-b .§raster{opacity:1}ø ø-cursor{|absolute;Ü:0¥ö|-26px -87px}∑ .light ø-cursor{ö|3px -87px}.S ø-cursor{ö|-34px -95px}.S .light ø-cursor{ö|-5px -95px}∑ .§panel{|absolute;top:10¥Ü:10¥bottom:10¥~94¥?~1¥?style:solid;?@#222 #555 #555 #222;overflow:hidden;ö@#333}.S .§panel{top:9¥Ü:9¥bottom:9px}.XS .§panel{display:none}.§panel div{|relative}«§hsv,«§hsl,«§rgb,«§cmyk,«§Lab,«§alpha,.no-alpha «§HEX,«§HEX{~86¥margin:-1px 0px 1px 4¥padding:1px 0px 3¥?top-~1¥?top-style:solid;?top-@#444;?bottom-~1¥?bottom-style:solid;?bottom-@#222;float:Ö«§hsv,«§hsl{padding-top:2px}.S .§hsv,.S .§hsl{padding-top:1px}«§HEX{?bottom-style:none;?top-~0¥margin-top:-4¥padding-top:0px}.no-alpha «§HEX{?bottom-style:none}«§alpha{?bottom-style:none}.S .rgb-r .§hsv,.S .rgb-g .§hsv,.S .rgb-b .§hsv,.S .rgb-r .§hsl,.S .rgb-g .§hsl,.S .rgb-b .§hsl,.S .hsv-h .§rgb,.S .hsv-s .§rgb,.S .hsv-v .§rgb,.S .hsl-h .§rgb,.S .hsl-s .§rgb,.S .hsl-l .§rgb,.S .§cmyk,.S .§Lab{display:none}«§butt,«§labl{float:left;~14¥ä14¥margin-top:2¥text-align:center;border:1px solid}«§butt{?@#555 #222 #222 #555}«§butt:active{ö@#444}«§labl{?@†}«Lab-mode,«cmyk-mode,«hsv-mode,«hsl-mode{|absolute;Ü:0¥top:1¥ä50px}«hsv-mode,«hsl-mode{top:2px}«cmyk-mode{ä68px}.hsl-h .hsl-h-labl,.hsl-s .hsl-s-labl,.hsl-l .hsl-l-labl,.hsv-h .hsv-h-labl,.hsv-s .hsv-s-labl,.hsv-v .hsv-v-labl{@#f90}«cmyk-mode,«hsv-mode,.rgb-r .rgb-r-butt,.rgb-g .rgb-g-butt,.rgb-b .rgb-b-butt,.hsv-h .hsv-h-butt,.hsv-s .hsv-s-butt,.hsv-v .hsv-v-butt,.hsl-h .hsl-h-butt,.hsl-s .hsl-s-butt,.hsl-l .hsl-l-butt,«rgb-r-labl,«rgb-g-labl,«rgb-b-labl,«alpha-butt,«HEX-butt,«Lab-x-labl{?@#222 #555 #555 #222;ö@#444}.no-rgb-r .rgb-r-labl,.no-rgb-g .rgb-g-labl,.no-rgb-b .rgb-b-labl,.mute-alpha .alpha-butt,.no-HEX .HEX-butt,.cmy-only .Lab-x-labl{?@#555 #222 #222 #555;ö@#333}.Lab-x-disp,.cmy-only .cmyk-k-disp,.cmy-only .cmyk-k-butt{visibility:hidden}«HEX-disp{öimage:none}«§disp{float:left;~48¥ä14¥margin:2px 2px 0¥cursor:text;text-align:left;text-indent:3¥?~1¥?style:solid;?@#222 #555 #555 #222}∑ .§nsarrow{|absolute;top:0¥left:-13¥~8¥ä16¥display:none;ö|-87px -23px}∑ .start-change .§nsarrow{display:block}∑ .do-change .§nsarrow{display:block;ö|-87px -36px}.do-change .§disp{cursor:default}«§hide{display:none}«§cont,«§cold{|absolute;top:-5¥left:0¥ä3¥border:1px solid #333}«§cold{z-index:1;ö@#c00}«§cont{margin-Ü:-1¥z-index:2}«contrast .§cont{z-index:1;ö@#ccc}«orange .§cold{ö@#f90}«green .§cold{ö@#4d0}«§ctrl{|absolute;bottom:0¥left:0¥~100%;ö@#fff}.alpha-bg-b .§ctrl,«§bres,«§bsav{ö@#333}«§col1,«§col2,«§bres,«§bsav{?~1¥?style:solid;?@#555 #222 #222 #555;float:left;~45¥line-ä28¥text-align:center;top:0px}.§panel div div{ä100%}.S .§ctrl div{line-ä25px}.S «§bres,.S «§bsav{line-ä26px}∑ .§exit,∑ .§resize{Ü:3¥top:3¥~15¥ä15¥ö|0 -52px}∑ .§resize{top:auto;bottom:3¥cursor:nwse-resize;ö|-15px -52px}.S .§exit{ö|1px -52px}.XS .§resize,.XS .§exit{~10¥ä10¥Ü:0¥öimage:none}.XS .§exit{top:0px}.XS .§resize{bottom:0px}∑ .§resizer,∑ .§resizer div{|absolute;border:1px solid #888;top:-1¥Ü:-1¥bottom:-1¥left:-1¥z-index:2;display:none;cursor:nwse-resize}∑ .§resizer div{border:1px dashed #333;opacity:0.3;display:block;ö@#bbb}' ).
    replace( /Ü/g, 'right' ).replace( /Ö/g, 'left}' ).replace( /∑/g, '.§app' ).replace( /«/g, '.§panel .' ).replace( /¥/g, 'px;' ).replace( /\|/g, 'position:' ).replace( /@/g, 'color:' ).replace( /ö/g, 'background-' ).replace( /ä/g, 'height:' ).replace( /ø/g, '.§memo' ).replace( /†/g, 'transparent' ).replace( /\~/g, 'width:' ).replace( /\?/g, 'border-' ).replace( /\^/g, '.§sld' ),
      _horizontalPng = 'iVBORw0KGgoAAAANSUhEUgAABIAAAAABCAYAAACmC9U0AAABT0lEQVR4Xu2S3Y6CMBCFhyqIsjGBO1/B9/F5DC/pK3DHhVkUgc7Zqus2DVlGU/cnQZKTjznttNPJBABA149HyRf1iN//4mIBCg0jV4In+j9xJiuihly1V/Z9X88v//kNeDXVvyO/lK+IPR76B019+1Riab3H1zkmeqerKnL+Bzwxx6PAgZxaSQU8vB62T28pxcQeRQ2sHw6GxCOWHvP78zwHAARBABOfdYtd30rwxXOEPDF+dj2+91r6vV/id3k+/brrXmaGUkqKhX3i+ffSt16HQ/dorTGZTHrs7ev7Tl7XdZhOpzc651nfsm1bRFF0YRiGaJoGs9nsQuN/xafTCXEco65rzOdzHI9HJEmCqqqwXC6x3++RZRnKssRqtUJRFFiv19jtdthutyAi5Hl+Jo9VZg7+7f3yXuvZf5c3KaXYzByb+WIzO5ymKW82G/0BNcFhO/tOuuMAAAAASUVORK5CYII=',
      _verticalPng = 'iVBORw0KGgoAAAANSUhEUgAAAAEAABfACAYAAABn2KvYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABHtJREFUeNrtnN9SqzAQxpOF1to6zuiVvoI+j6/gva/lA/kKeqUzjtX+QTi7SzSYBg49xdIzfL34+e1usoQQklCnmLwoCjImNwDQA2xRGMqNAYB+gPEH9IdCgIUA6Aem0P1fLoMQAPYNHYDoCKAv8OMHFgKgX2AjDPQDXn4t1l+gt/1fId//yWgE/hUJ+mAn8EyY5wCwXxhrbaHzn8E9iPlv79DdHxXTqciZ4KROnXRVZMF/6U2OPhcEavtAbZH1SM7wRDD7VoHZItCiyEQf4t6+MW9UOxaZybmdCGKqNrB9Eb5SfMg3wTyiagMtigTmWofiSDCOYNTSNz6sLDIoaCU9GWDd0tdhoMMsRm+r8U/EfB0GfjmLXiqzimDd0tdhoLMsI7la45+I+ToM/HIW0kfGVQTrlr7tA91kaUr//fxrKo8jUFB7VAn6AKpHJf+EKwAAAIYD/f7F7/8MVgMo7P+gBqDKr57Lf72V8x8AAMDgYIuvH4EAAAAMDQX6AACAQcI9GGMjDADA4MA/P2KlP8IEAAAYFCz6AACAgaLA8y8AAIN+CMYXoQAADA7u/UPYCAMAMDjI7z9S+SdwDFQX2C9Gh9GMEOWriz8/Pw1lWQZsi/L3R4czzP678Ve+P8f9nCv/C7hwLq99ah8NfKrU15zPB5pVcwtiJt9qGy0IfEE+jQa+Fn0VtI/fkxUPqBlEfRENeF+tqUpbGpi1iu8epwJzvV5XA4GpWC6XGz7F+/u766EgwJ+ckiTJKU3TnI6OjnI6OzvLZf6zMggt3dzckPhIoiTlSGpQ+eEsVegdz0fbCCi4fRs+Po+4yWdeDXiT+6pBSTeHple1pkz3FZ+avpyavoiPxgLN0B7yprY08PlyQTTm0+PWmkH7ynedNKraar4F/lRj1WpTtYh+ozL/cY2sAvZl0gcbZm0gSLBLvkxGoaogiy/HDXemQk2t5pUm8OAhH8/HH6e0mkJ9q9XKKQXfb07xfZnJbZrRxcVFVt6/t7e3Kc1ms5RGo1Eq5VIZuyl9fHw4k/M5xYeoKj64A7eqCt1ZeqWFVSl8NV9OTV3fmvP5qE9VmzSoEcsXpArK1UHen/hZbgL53BZSdyEXalGau/hU8TEW0u3VcoFPy3EDFrTgT+njydeZ0+l0UV7fu7u7iVzziQQmUm4iqRw4n/NxMxw4s/Mp1NSALxf4NEtQ10cjMDwSl+b+/j6hp6enVGb+jUvrn05iKobm6PboOt8vPISY5Pr6OqGXlxe3fOokoGtAbMUJZmqvYmaLQDP+sdrecOjtO/SXeH69P8Imutm5urqy9PDwYOny8tLS4+OjpfPzc0vPz8+WTk9PLb2+vlpZbCzN53NLx8fHVtYZS5PJxMoEZWWqsjKULY3HYytTi1Pex5OMldXKRVXxuLcy/20onmms3BBOxcr5qCrZtsrd45SPel8sGlOxGoGy0neynQ6VL9fsa1YtWlCrtj9G83G7PjdVush5n5q1iJWLZW6u21a1bUvbVnVzlru0pe3RdmlV1/23fZtbZv4Dx+7FBypx77kAAAAASUVORK5CYII=',
      _patchesPng = ( 'iVBORw0KGgo^NSUhEUgAAB4^EACAI#DdoPxz#L0UlEQVR4Xu3cQWrDQBREwR7FF8/BPR3wXktnQL+KvxfypuEhvLJXcp06d/bXd71OPt+trIw95zr33Z1bk1/fudEv79wa++7OfayZ59wrO2PBzklcGQmAZggAAOBYgAYBmpWRAGg^BGgRofAENgAAN#I0CBA6w8AG^ECABgEa/QH§AI0CNDoDwAY^QIAGAVp/AM§AjQI0OgPAAY^QoEGARn8Aw§CNAjQ+gMABg#BCgQYCmGQmABgAAEKBBgEZ/AM§AjQI0PoDAAY^QoEGARn8AM^IAADQI0+gMABg#BCgQYDWHwAw^gAANAjT6A4AB^BGgQoNEfAD^C#0CtP4AgAE^EaBCgaUYCoAE#RoEKDRHwAw^gAANArT+AIAB^BGgQoNEfAAw^gQIMAjf4AgAE^EaBCg9QcAD^CBAgwCN/gBg§EaBGj0BwAM^IECDAK0/AG§ARoEaJqRAGg^BGgRo9AcAD^CBAgwCtPwBg§EaBGj0BwAD^CNAgQKM/AG§ARoEaP0BAAM^I0CBAoz8AG^ECABgEa/QEAAw^jQIEDrDwAY^QIAGAZpmJACaBw^RoEKD1BwAM^IECDAK0/AG§ARoEaPQHAAw^gQIMArT8AY§BGgRo/QEAAw^jQIECjPwBg§EaBGj9AQAD^CNAgQOsPABg#BAgAYBGv0BAANwCwAAGB6gYeckmpEAa^AEaBGj0BwAM^IECDAK0/AG§ARoEaPQHAAM^I0CBAoz8AY§BGgRo/QEAAw^jQIECjPwAY^QIAGARr9AQAD^CNAgQOsPABg#BAgAYBmmYkABoAAECABgEa/QEAAw^jQIEDrDwAY^QIAGARr9Ac§AjQI0OgPABg#BAgAYBWn8Aw§CNAjQ6A8ABg#BCgQYBGfwD§AI0CND6AwAG^EKBBgKYZCYAG#QoEGARn8Aw§CNAjQ+gMABg#BCgQYBGfwAw^gAANAjT6AwAG^EKBBgNYfAD^C#0CNPoDgAE^EaBCg0R8AM^IAADQK0/gCAAQ^RoEKBpRgKgAQAABGgQoNEfAD^C#0CtP4AgAE^EaBCg0R8AD^CBAgwCN/gCAAQ^RoEKD1BwAM^IECDAI3+AG§ARoEaPQHAAw^gQIMArT8AY§BGgRomsMAM^IAADQK0/gCAAQ^RoEKDRHwAw^gAANO7fQHwAw^gAANArT+AIAB^BGgQoNEfAGg^BGgRo9AcAD^CBAgwCtPwBg§EaBGj0BwAD^RIB+Ntg5iea5AD^DAIwI0CND6AwAG^EKBBgEZ/AKAB#EaBCg0R8AM^IAADQK0/gCAAQ^RoEKDRHwAM^IECDAI3+AIAB^BGgQoPUHAAw^gQIMAjf4AY§BGgRo9AcAD^CBAgwCtPwBg§EaBGiakQBo^ARoEaPQHAAw^gQIMArT8AY§BGgRo9AcAAw^jQIECjPwBg§EaBGj9AQAD^CNAgQKM/ABg#BAgAYBGv0BAAM^I0CBA6w8AG^ECABgGaZiQAGgAAQIAGARr9AQAD^CNAgQOsPABg#BAgAYBGv0Bw§CNAjQ6A8AG^ECABgFafwD§AI0CNDoDwAG^EKBBgEZ/AM§AjQI0PoDAAY^QoEGApjkMAAM^I0CBA6w8AG^ECABgEa/QEAAw^jQsIP+AIAB^BGgQoPUHAAw^gQIMAjf4AgAE#Bea/fK+3P5/3PJOvh8t1cO4nflmQAQoAEAAF9Aw/7JHfQHAAw^gQIMArT8AY§BGvwHNPoDAA0AACBAgwCN/gCAAQ^RoEKD1BwAM^IECDAI3+AG§ARoEaPQHAAw^gQIMArT8AY§BGgRo9AcAAw^jQIECjPwBg§EaBGj9AQAD^CNAgQNOMBEAD#I0CBAoz8AY§BGgRo/QEAAw^jQIECjPwAY^QIAGARr9AQAD^CNAgQOsPABg#BAgAYBGv0Bw§CNAjQ6A8AG^ECABgFafwD§AI0CNA0IwHQ^AjQI0OgPABg#BAgAYBWn8Aw§CNAjQ6A8ABg#BCgQYBGfwD§AI0CND6AwAG^EKBBgEZ/AD^C#0CNPoDAAY^QoEGA1h8AM^IAADQI0DQAG^EKBBgEZ/AM§AjQI0PoDAAY^QoEGA1h8AM^IAADQI0+gMABg#BCgQYDWHwAw^gAANArT+AIAB^BGgQoNEfAD^C#0CtP4AgAE^EaBCg9QcAD^CBAgwCN/gCAAQ^RoEKD1BwAM^IECDAK0/AG§ARoEaPQHAAw^gQIMArT8AY§BGgRo/QEAAw^jQIECjPwBgACDhFgC#07t9AfAD^C#0CtP4AgAE^EaBCg0R8Aa^AEaBGj0BwAM^IECDAK0/AG§ARoEaPQHAAM^I0CBAoz8AY§BGgRo/QEAAw^jQIECjPwAY^QIAGARr9AQAD^CNAgQOsPABg#BAgAYBmmYkABoAAECABgEa/QEAAw^jQIEDrDwAY^QIAGARr9Ac§AjQI0OgPABg#BAgAYBWn8Aw§CNAjQ6A8ABg#BCgQYBGfwD§AI0CND6AwAG^EKBBgKYZCYAG#QoEGARn8Aw§CNAjQ+gMABg#BCgQYBGfwAw^gAANAjT6AwAG^EKBBgNYfAD^C#0CNPoDgAE^EaBCg0R8AM^IAADQK0/gCAAQ^RoEKBpRgKgAQAABGgQoNEfAD^C#0CtP4AgAE^EaBCg0R8AD^CBAgwCN/gCAAQ^RoEKD1BwAM^IECDAI3+AG§ARoEaPQHAAw^gQIMArT8AY§BGgRommEAM^CBAgwCN/gCAAQ^RoEKD1BwAM^IECDAI3+AIAB^ARoEaPQHAAw^gQIMArT8AY§BGgRo9AcAGgAAQICGCNBfRfNcABg#BgeICGnVvoDwAY^QIAGAVp/AM§AjQI0OgPADQAAIAADQI0+gMABg#BCgQYDWHwAw^gAANAjT6A4AB^BGgQoNEfAD^C#0CtP4AgAE^EaBCg0R8AD^CBAgwCN/gCAAQ^RoEKD1BwAM^IECDAE0zEgAN#gQIMAjf4AgAE^EaBCg9QcAD^CBAgwCN/gBg§EaBGj0BwAM^IECDAK0/AG§ARoEaPQHAAM^I0CBAoz8AY§BGgRo/QEAAw^jQIEDTjARAAwAACNAgQKM/AG§ARoEaP0BAAM^I0CBAoz8AG^ECABgEa/QEAAw^jQIEDrDwAY^QIAGARr9Ac§AjQI0OgPABg#BAgAYBWn8Aw§CNAjQNIcBY§BGgRo/QEAAw^jQIECjPwBg§EadtAfAD^C#0CtP4AgAE^EaBCgAQABGgAA+AO2TAbHupOgH^ABJRU5ErkJggg==' ).
    replace( /§/g, 'AAAAAA' ).replace( /\^/g, 'AAAA' ).replace( /#/g, 'AAA' ),
      _iconsPng = 'iVBORw0KGgoAAAANSUhEUgAAAGEAAABDCAMAAAC7vJusAAAAkFBMVEUAAAAvLy9ERERubm7///8AAAD///9EREREREREREREREQAAAD///8AAAD///8AAAD///8AAAD///8AAAD///8AAAD///8AAAD///8AAAD///8AAAD///8cHBwkJCQnJycoKCgpKSkqKiouLi4vLy8/Pz9AQEBCQkJDQ0NdXV1ubm58fHykpKRERERVVVUzMzPx7Ab+AAAAHXRSTlMAAAAAAAQEBQ4QGR4eIyMtLUVFVVVqapKSnJy7u9JKTggAAAFUSURBVHja7dXbUoMwEAbgSICqLYeW88F6KIogqe//dpoYZ0W4AXbv8g9TwkxmvtndZMrEwlw/F8YIRjCCEYxgBCOsFmzqGMEI28J5zzmt0Pc9rdDL0NYgMxIYC5KiKpKAzZphWtZlGm4SjlnkOV6UHeeEUx77rh/npw1dCrI9k9lnwUwF+UG9D3m4ftJJxH4SJdPtaawXcbr+tBaeFrxiur309cIv19+4ytGCU0031a5euPVigLYGqjlAqM4ShOQ+QAYQUO80AMMAAkUGGfMfR9Ul+kmvPq2QGxXKOQBAKdjUgk0t2NiCGEVP+rHT3/iCUMBT90YrPMsKsIWP3x/VolaonJEETchHCS8AYAmaUICQQwaAQnjoXgHAES7jLkEFaHO4bdq/k25HAIpgWY34FwAE5xjCffM+D2DV8B0gRsAZT7hr5gE8wdrJcU+CJqhcqQD7Cx5L7Ph4WnrKAAAAAElFTkSuQmCC',
      _bgsPng = 'iVBORw0KGgoAAAANSUhEUgAAASAAAABvCAYAAABM+h2NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABORJREFUeNrs3VtTW1UYBuCEcxAI4YydWqTWdqr1V7T/2QsvvPDCCy9qjxZbamsrhZIQUHsCEtfafpmJe8qFjpUxfZ4Zuvt2feydJvAOARZUut1u5bRerl692nV913f99/f6QxWAU6KAAAUEKCAABQQoIAAFBCggAAUEKCAABQQoIAAFBCggAAUEKCAABQQoIEABASggQAEBKCBAAQEoIEABASggQAEBKCBAAQEoIGBQC+jatWvd07zxrv9+Xx8fAQEoIEABASggQAEBKCBAAQEoIEABAQoIQAEBCghAAQEKCEABAQOk2u36kS6AAgLetwJKL29toFRM1be+QrVq3rx58//KvM8BAadGAQEKCFBAAAoIGHwnfhneZ+/Nmzf/LufzrI+AAE/BAAUEoIAABQTwztgLZt68eXvBAE/BABQQoIAAFBAweOwFM2/evL1ggKdgAAoIUEAACggYPPaCmTdv3l4wwFMwAAUEKCAABQQMHnvBzJs3by8Y4CkYgAICFBCAAgIGz4lfBQNQQMDgFlCtVisaaHV1tThubW1VInciD0U+ysdnz54N5+PKysphOnRTHsvHlN9EHo/1l5FrkV9Enoz8W87b29tTOS8vLx9EnoncjlyPvBe5EbkZeT4fU96NvBDr2znv7Ows57y0tLQVeSXy08gf5mNfPhPrjyOfrVarlcXFxZ9yfv78+bl8TPlh5LU8n/KDyOuxfj/y+VjfyHl3d/dCKv28fi/yp/m4sLDwQ+SLke9GvhT5Tinfjnw5f4/F/Pz8rZybzeZn+ZjyzVK+EfnzUr4S+Xopf9/L+fxzc3M5d1qt1hf531Mu5k/IxzGf85VYL+fefHH+RqNRrO/t7RW3L+UbkS9Hvhk5/386Kd/qW8/5duRLMV/OdyJfzNebnZ0t7t92u53v/07K9yJfiLwROT9+ef7HyOux/iDyWuSHkT+K+eLtZX9//2xer9frjyOfyY9/Wn8S86v59qT1p7Ge315zLt4RU16K19+O9YXIu5HnYn435hux3opcj9yOPB3z+5E/iPXf43y1yMX778HBQS3f3pTz+28l5bHIr2N+LN3+zszMzGHkoh/S+mHMF98XlNaP8zHd/0W/pMe943NAwKlSQIACAhQQgAICFBCAAgIUEIACAhQQgAIC/n9GqtXqYbfbHa38+RtSu32llPdqdNL6aOSj+LfxyMVekLTem39Ryr/mPDQ0NBznzXtROikPRW6W8k7k3m9rzXthOsPDw73bUuylGRkZ6cR63nvTSfko8oPIr+Pnz96P/DLW816ezujoaN6DdtyX9+P8eS9QZ2xs7Hxf7qa8Xlr/JO6Ljcjrcf6cj1P+OO+N6V1/fHz8XLz+/Tjfubh+sZcorZ+N9Ycxfybyo8ircf6fc56YmFiJ1/8l8mLk7cjzkfP92U15Ns63G+u9nPcKdWq12lQ8Xu3Ixd6f9Pd8P3UmJycnUszzL2N9LM7/anNzs9V7Q2q32395w/q7ubdH6L/KrVbrpPxlKX9Vyl+X8jel/G0pf5f/aDabvXy9tH6ztH63lDdKebOUH5Xyk1LeKuWd/ry2tlap9P125Onp6Zf9eWpq6lW3b8f6zMzM6/71er3+ppSP+u/XNN/pz41Go+sjIMBTMEABASggQAEBKCBAAQEoIEABASggQAEB/CN/CDAAw78uW9AVDw4AAAAASUVORK5CYII=';

    window.ColorPicker = {
      _html: _html,
      _cssFunc: _cssFunc,
      _cssMain: _cssMain,
      _horizontalPng: _horizontalPng,
      _verticalPng: _verticalPng,
      _patchesPng: _patchesPng,
      _iconsPng: _iconsPng,
      _bgsPng: _bgsPng
    }
  } )( window );

  ;
  ( function( window, undefined ) {
    "use strict"

    var _data = window.ColorPicker, // will be deleted in buildView() and holds:
      // window.ColorPicker = { // comes from colorPicker.data.js and will be overwritten.
      // 	_html: ..., // holds the HTML markup of colorPicker
      // 	_cssFunc: ..., // CSS for all the sliders
      // 	_cssMain: ..., // CSS of the GUI
      // 	_horizontalPng: ..., // horizontal background images for sliders
      // 	_verticalPng: ..., // vertical background images for sliders
      // 	_patchesPng: ..., // background images for square sliders in RGB mode
      // 	_iconsPng: ..., // some icon sprite images
      // 	_bgsPng: ..., // some more icon sprite images
      // }
      _devMode = !_data, // if no _data we assume that colorPicker.data.js is missing (for development)
      _isIE = false,
      _doesOpacity = false,
      // _isIE8 = _isIE && document.querySelectorAll,

      _valueRanges = {}, // will be assigned in initInstance() by Colors instance
      // _valueRanges = {
      // 	rgb:   {r: [0, 255], g: [0, 255], b: [0, 255]},
      // 	hsv:   {h: [0, 360], s: [0, 100], v: [0, 100]},
      // 	hsl:   {h: [0, 360], s: [0, 100], l: [0, 100]},
      // 	cmyk:  {c: [0, 100], m: [0, 100], y: [0, 100], k: [0, 100]},
      // 	cmy:   {c: [0, 100], m: [0, 100], y: [0, 100]},
      // 	XYZ:   {X: [0, 100], Y: [0, 100], Z: [0, 100]},
      // 	Lab:   {L: [0, 100], a: [-128, 127], b: [-128, 127]},
      // 	alpha: {alpha: [0, 1]},
      // 	HEX:   {HEX: [0, 16777215]}
      // },
      _bgTypes = {
        w: 'White',
        b: 'Black',
        c: 'Custom'
      },

      _mouseMoveAction, // current mouseMove handler assigned on mouseDown
      _action = '', // needed for action callback; needed due to minification of javaScript
      _mainTarget, // target on mouseDown, might be parent element though...
      _valueType, // check this variable; gets missused/polutet over time
      _delayState = 1, // mouseMove offset (y-axis) in display elements // same here...
      _startCoords = {},
      _targetOrigin = {},
      _renderTimer, // animationFrame/interval variable
      _newData = true,
      // _txt = {
      // 	selection: document.selection || window.getSelection(),
      // 	range: (document.createRange ? document.createRange() : document.body.createTextRange())
      // },

      _renderVars = {}, // used only in renderAll and convertColors
      _cashedVars = {}, // reset in initSliders

      _colorPicker,
      _previousInstance, // only used for recycling purposes in buildView()
      _colorInstance = {},
      _colors = {},
      _options = {},
      _nodes = {},

      _math = Math,

      animationFrame = 'AnimationFrame', // we also need this later
      requestAnimationFrame = 'request' + animationFrame,
      cancelAnimationFrame = 'cancel' + animationFrame,
      vendors = [ 'ms', 'moz', 'webkit', 'o' ],

      ColorPicker = function( options ) { // as tiny as possible...
        this.options = {
          color: 'rgba(204, 82, 37, 0.8)',
          mode: 'rgb-b',
          fps: 60, // 1000 / 60 = ~16.7ms
          delayOffset: 8,
          CSSPrefix: 'cp-',
          allMixDetails: true,
          alphaBG: 'w',
          imagePath: ''
            // devPicker: false // uses existing HTML for development...
            // noAlpha: true,
            // customBG: '#808080'
            // size: 0,
            // cmyOnly: false,
            // initStyle: 'display: none',

          // memoryColors: "'rgba(82,80,151,1)','rgba(100,200,10,0.5)','rgba(100,0,0,1)','rgba(0,0,0,1)'"
          // memoryColors: [{r: 100, g: 200, b: 10, a: 0.5}] //  

          // opacityPositionRelative: undefined,
          // customCSS: undefined,
          // appendTo: document.body,
          // noRangeBackground: false,
          // textRight: false, ?????
          // noHexButton: false,
          // noResize: false,

          // noRGBr: false,
          // noRGBg: false,
          // noRGBb: false,

          // ------ CSSStrength: 'div.',
          // XYZMatrix: XYZMatrix,
          // XYZReference: {},
          // grey: grey,
          // luminance: luminance,

          // renderCallback: undefined,
          // actionCallback: undefined,
          // convertCallback: undefined,
        };
        initInstance( this, options ||  {} );
      };

    window.ColorPicker = ColorPicker; // export differently
    ColorPicker.addEvent = addEvent;
    ColorPicker.removeEvent = removeEvent;
    ColorPicker.getOrigin = getOrigin;
    ColorPicker.limitValue = limitValue;
    ColorPicker.changeClass = changeClass;

    // ------------------------------------------------------ //

    ColorPicker.prototype.setColor = function( newCol, type, alpha, forceRender ) {
      focusInstance( this );
      _valueType = true; // right cursor...
      // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers
      preRenderAll( _colorInstance.setColor.apply( _colorInstance, arguments ) );
      if ( forceRender ) {
        this.startRender( true );
      }
    };

    ColorPicker.prototype.saveAsBackground = function() {
      focusInstance( this );
      return saveAsBackground( true );
    };

    ColorPicker.prototype.setCustomBackground = function( col ) {
      focusInstance( this ); // needed???
      return _colorInstance.setCustomBackground( col );
    };

    ColorPicker.prototype.startRender = function( oneTime ) {
      focusInstance( this );
      if ( oneTime ) {
        _mouseMoveAction = false; // prevents window[requestAnimationFrame] in renderAll()
        renderAll();
        this.stopRender();
      } else {
        _mouseMoveAction = 1;
        _renderTimer = window[ requestAnimationFrame ]( renderAll );
      }
    };

    ColorPicker.prototype.stopRender = function() {
      focusInstance( this ); // check again
      window[ cancelAnimationFrame ]( _renderTimer );
      if ( _valueType ) {
        // renderAll();
        _mouseMoveAction = 1;
        stopChange( undefined, 'external' );
        // _valueType = undefined;
      }
    };

    ColorPicker.prototype.setMode = function( mode ) { // check again ... right cursor
      focusInstance( this );
      setMode( mode );
      initSliders();
      renderAll();
    };

    ColorPicker.prototype.destroyAll = function() { // check this again...
      var html = this.nodes.colorPicker,
        destroyReferences = function( nodes ) {
          for ( var n in nodes ) {
            if ( nodes[ n ] && nodes[ n ].toString() === '[object Object]' || nodes[ n ] instanceof Array ) {
              destroyReferences( nodes[ n ] );
            }
            nodes[ n ] = null;
            delete nodes[ n ];
          }
        };

      this.stopRender();
      installEventListeners( this, true );
      destroyReferences( this );
      html.parentNode.removeChild( html );
      html = null;
    };

    ColorPicker.prototype.renderMemory = function( memory ) {
      var memos = this.nodes.memos,
        tmp = [];

      if ( typeof memory === 'string' ) { // revisit!!!
        memory = memory.replace( /^'|'$/g, '' ).replace( /\s*/, '' ).split( '\',\'' );
      }
      for ( var n = memos.length; n--; ) { // check again how to handle alpha...
        if ( memory && typeof memory[ n ] === 'string' ) {
          tmp = memory[ n ].replace( 'rgba(', '' ).replace( ')', '' ).split( ',' );
          memory[ n ] = {
            r: tmp[ 0 ],
            g: tmp[ 1 ],
            b: tmp[ 2 ],
            a: tmp[ 3 ]
          }
        }
        memos[ n ].style.cssText = 'background-color: ' + ( memory && memory[ n ] !== undefined ?
          color2string( memory[ n ] ) + ';' + getOpacityCSS( memory[ n ][ 'a' ] ||  1 ) : 'rgb(0,0,0);' );
      }
    };

    // ------------------------------------------------------ //

    function initInstance( THIS, options ) {
      var exporter, // do something here..
        mode = '',
        CSSPrefix = '',
        optionButtons;

      for ( var option in options ) { // deep copy ??
        THIS.options[ option ] = options[ option ];
      }
      _isIE = document.createStyleSheet !== undefined && document.getElementById || !!window.MSInputMethodContext;
      _doesOpacity = typeof document.body.style.opacity !== 'undefined';
      _colorInstance = new Colors( THIS.options );
      // We transfer the responsibility to the instance of Color (to save space and memory)
      delete THIS.options;
      _options = _colorInstance.options;
      _options.scale = 1;
      CSSPrefix = _options.CSSPrefix;

      THIS.color = _colorInstance; // check this again...
      _valueRanges = _options.valueRanges;
      THIS.nodes = _nodes = getInstanceNodes( buildView( THIS ), THIS ); // ha, ha,... make this different
      setMode( _options.mode );
      focusInstance( THIS );
      saveAsBackground();

      mode = ' ' + _options.mode.type + '-' + _options.mode.z;
      _nodes.slds.className += mode;
      _nodes.panel.className += mode;
      //_nodes.colorPicker.className += ' cmy-' + _options.cmyOnly;

      if ( _options.noHexButton ) {
        changeClass( _nodes.HEX_butt, CSSPrefix + 'butt', CSSPrefix + 'labl' );
      }

      if ( _options.size !== undefined ) {
        resizeApp( undefined, _options.size );
      }

      optionButtons = {
        alphaBG: _nodes.alpha_labl,
        cmyOnly: _nodes.HEX_labl // test... take out
      };
      for ( var n in optionButtons ) {
        if ( _options[ n ] !== undefined ) {
          buttonActions( {
            target: optionButtons[ n ],
            data: _options[ n ]
          } );
        }
      }
      if ( _options.noAlpha ) {
        _nodes.colorPicker.className += ' no-alpha'; // IE6 ??? maybe for IE6 on document.body
      }

      THIS.renderMemory( _options.memoryColors );

      installEventListeners( THIS );

      _mouseMoveAction = true;
      stopChange( undefined, 'init' );

      if ( _previousInstance ) {
        focusInstance( _previousInstance );
        renderAll();
      }
    }

    function focusInstance( THIS ) {
      _newData = true;
      if ( _colorPicker !== THIS ) {
        _colorPicker = THIS;
        _colors = THIS.color.colors;
        _options = THIS.color.options;
        _nodes = THIS.nodes;
        _colorInstance = THIS.color;

        _cashedVars = {};
        preRenderAll( _colors );
      }
    }

    function getUISizes() {
      var sizes = [ 'L', 'S', 'XS', 'XXS' ];
      _options.sizes = {};
      _nodes.testNode.style.cssText = 'position:absolute;left:-1000px;top:-1000px;';
      document.body.appendChild( _nodes.testNode );
      for ( var n = sizes.length; n--; ) {
        _nodes.testNode.className = _options.CSSPrefix + 'app ' + sizes[ n ];
        _options.sizes[ sizes[ n ] ] = [ _nodes.testNode.offsetWidth, _nodes.testNode.offsetHeight ];
      }
      if ( _nodes.testNode.removeNode ) { // old IEs
        _nodes.testNode.removeNode( true );
      } else {
        document.body.removeChild( _nodes.testNode );
      }
    }

    function buildView( THIS ) {
      var app = document.createElement( 'div' ),
        prefix = _options.CSSPrefix,
        urlData = 'data:image/png;base64,',
        addStyleSheet = function( cssText, id ) {
          var style = document.createElement( 'style' );

          style.setAttribute( 'type', 'text/css' );
          if ( id ) {
            style.setAttribute( 'id', id );
          }
          if ( !style.styleSheet ) {
            style.appendChild( document.createTextNode( cssText ) );
          }
          document.getElementsByTagName( 'head' )[ 0 ].appendChild( style );
          if ( style.styleSheet ) { // IE compatible
            document.styleSheets[ document.styleSheets.length - 1 ].cssText = cssText;
          }
        },
        processCSS = function( doesBAS64 ) {
          // CSS - system
          _data._cssFunc = _data._cssFunc.
          replace( /§/g, prefix ).
          replace( '_patches.png', doesBAS64 ? urlData + _data._patchesPng : _options.imagePath + '_patches.png' ).
          replace( '_vertical.png', doesBAS64 ? urlData + _data._verticalPng : _options.imagePath + '_vertical.png' ).
          replace( '_horizontal.png', doesBAS64 ? urlData + _data._horizontalPng :
            _options.imagePath + '_horizontal.png' );
          addStyleSheet( _data._cssFunc, 'colorPickerCSS' );
          // CSS - main
          if ( !_options.customCSS ) {
            _data._cssMain = _data._cssMain.
            replace( /§/g, prefix ).
            replace( '_bgs.png', doesBAS64 ? urlData + _data._bgsPng : _options.imagePath + '_bgs.png' ).
            replace( '_icons.png', doesBAS64 ? urlData + _data._iconsPng : _options.imagePath + '_icons.png' ).
              // replace('"Courier New",', !_isIE ? '' : '"Courier New",').
            replace( /opacity:(\d*\.*(\d+))/g, function( $1, $2 ) {
              return !_doesOpacity ? '-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=' +
                _math.round( +$2 * 100 ) + ')";filter: alpha(opacity=' + _math.round( +$2 * 100 ) + ')' :
                '-moz-opacity: ' + $2 + '; -khtml-opacity: ' + $2 + '; opacity: ' + $2;
            } );
            // style.appendChild(document.createTextNode(_data._cssFunc));
            addStyleSheet( _data._cssMain );
          }
          // for (var n in _data) { // almost 25k of memory ;o)
          // 	_data[n] = null;
          // }
        },
        test = document.createElement( 'img' );

      // development mode
      if ( _devMode ) {
        return THIS.color.options.devPicker;
      }

      // CSS
      if ( !document.getElementById( 'colorPickerCSS' ) ) { // only once needed
        test.onload = test.onerror = function() {
          if ( _data._cssFunc ) {
            processCSS( this.width === 1 && this.height === 1 );
          }
          THIS.cssIsReady = true;
        };
        test.src = "";
      } else {
        THIS.cssIsReady = true;
      }

      // HTML
      if ( _previousInstance = _colorPicker ) {
        // we need to be careful with recycling HTML as slider calssNames might have been changed...
        initSliders();
      }
      // app.innerHTML = _colorPicker ? _colorPicker.nodes.colorPicker.outerHTML : _data._html.replace(/§/g, prefix);
      // faster ... FF8.0 (2011) though (but IE4)
      // outerHTML ... FF11 (2013)
      app.insertAdjacentHTML( 'afterbegin',
        _colorPicker ? _colorPicker.nodes.colorPicker.outerHTML ||
        new XMLSerializer().serializeToString( _colorPicker.nodes.colorPicker ) : // FF before F11
        _data._html.replace( /§/g, prefix ) );
      // _colorPicker ? _colorPicker.nodes.colorPicker.parentNode.innerHTML : _data._html.replace(/§/g, prefix));
      // _data._html = null;

      app = app.children[ 0 ];
      app.style.cssText = _options.initStyle || ''; // for initial hiding...
      // get a better addClass for this....
      // app.className = app.className.split(' ')[0]; // cleanup for multy instances

      return ( _options.appendTo || document.body ).appendChild( app );
    }

    function getInstanceNodes( colorPicker, THIS ) { // check nodes again... are they all needed?
      var all = colorPicker.getElementsByTagName( '*' ),
        nodes = {
          colorPicker: colorPicker
        }, // length ?? // rename nodes.colorPicker
        node,
        className,
        memoCounter = 0,
        regexp = new RegExp( _options.CSSPrefix );

      // nodes.displayStyles = {}; // not needed ... or change to CSS
      nodes.styles = {};
      // nodes.styles.displays = {};

      nodes.textNodes = {};
      nodes.memos = [];
      nodes.testNode = document.createElement( 'div' );

      for ( var n = 0, m = all.length; n < m; n++ ) {
        node = all[ n ];
        if ( ( className = node.className ) && regexp.test( className ) ) {
          className = className.split( ' ' )[ 0 ].replace( _options.CSSPrefix, '' ).replace( /-/g, '_' );
          if ( /_disp/.test( className ) ) {
            className = className.replace( '_disp', '' );
            // nodes.styles.displays[className] = node.style;
            nodes.styles[ className ] = node.style;
            nodes.textNodes[ className ] = node.firstChild;
            node.contentEditable = true; // does this slow down rendering??
          } else {
            if ( !( /(?:hs|cmyk|Lab).*?(?:butt|labl)/.test( className ) ) ) {
              nodes[ className ] = node;
            }
            if ( /(?:cur|sld[^s]|opacity|cont|col)/.test( className ) ) {
              nodes.styles[ className ] = /(?:col\d)/.test( className ) ? node.children[ 0 ].style : node.style;
            }
          }
        } else if ( /memo/.test( node.parentNode.className ) ) {
          nodes.memos.push( node );
        }
      }

      // Chrome bug: focuses contenteditable on mouse over while dragging
      nodes.panelCover = nodes.panel.appendChild( document.createElement( 'div' ) );

      return nodes;
    }

    // ------------------------------------------------------ //
    // ---- Add event listners to colorPicker and window ---- //
    // -------------------------------------------------------//

    function installEventListeners( THIS, off ) {
      var onOffEvent = off ? removeEvent : addEvent;

      onOffEvent( _nodes.colorPicker, 'mousedown', function( e ) {
        var event = e || window.event,
          page = getPageXY( event ),
          target = ( event.button || event.which ) < 2 ?
          ( event.target || event.srcElement ) : {},
          className = target.className;

        focusInstance( THIS );
        _mainTarget = target;
        stopChange( undefined, 'resetEventListener' );
        _action = ''; // needed due to minification of javaScript

        if ( target === _nodes.sldl_3 || target === _nodes.curm ) {
          _mainTarget = _nodes.sldl_3;
          _mouseMoveAction = changeXYValue;
          _action = 'changeXYValue';
          changeClass( _nodes.slds, 'do-drag' );
        } else if ( /sldr/.test( className ) || target === _nodes.curl || target === _nodes.curr ) {
          _mainTarget = _nodes.sldr_4;
          _mouseMoveAction = changeZValue;
          _action = 'changeZValue';
        } else if ( target === _nodes.opacity.children[ 0 ] || target === _nodes.opacity_slider ) {
          _mainTarget = _nodes.opacity;
          _mouseMoveAction = changeOpacityValue;
          _action = 'changeOpacityValue';
        } else if ( /-disp/.test( className ) && !/HEX-/.test( className ) ) {
          _mouseMoveAction = changeInputValue;
          _action = 'changeInputValue';
          ( target.nextSibling.nodeType === 3 ? target.nextSibling.nextSibling : target.nextSibling ).
          appendChild( _nodes.nsarrow ); // nextSibling for better text selection
          _valueType = className.split( '-disp' )[ 0 ].split( '-' );
          _valueType = {
            type: _valueType[ 0 ],
            z: _valueType[ 1 ] || ''
          };
          changeClass( _nodes.panel, 'start-change' );
          _delayState = 0;
        } else if ( target === _nodes.resize && !_options.noResize ) {
          if ( !_options.sizes ) {
            getUISizes();
          }
          _mainTarget = _nodes.resizer;
          _mouseMoveAction = resizeApp;
          _action = 'resizeApp';
        } else {
          _mouseMoveAction = undefined;
        }

        if ( _mouseMoveAction ) {
          _startCoords = {
            pageX: page.X,
            pageY: page.Y
          };
          _mainTarget.style.display = 'block'; // for resizer...
          _targetOrigin = getOrigin( _mainTarget );
          _targetOrigin.width = _nodes.opacity.offsetWidth; // ???????
          _targetOrigin.childWidth = _nodes.opacity_slider.offsetWidth; // ???????
          _mainTarget.style.display = ''; // ??? for resizer...
          _mouseMoveAction( event );
          addEvent( _isIE ? document.body : window, 'mousemove', _mouseMoveAction );
          _renderTimer = window[ requestAnimationFrame ]( renderAll );
        } else {
          // console.log(className)
          // console.log(THIS.nodes[className.split(' ')[0].replace('cp-', '').replace('-', '_')])
          // resize, button states, etc...
        }

        // if (_mouseMoveAction !== changeInputValue) preventDefault(event);
        if ( !/-disp/.test( className ) ) {
          return preventDefault( event );
          // document.activeElement.blur();
        }
      } );

      onOffEvent( _nodes.colorPicker, 'click', function( e ) {
        focusInstance( THIS );
        buttonActions( e );
      } );

      onOffEvent( _nodes.colorPicker, 'dblclick', buttonActions );

      onOffEvent( _nodes.colorPicker, 'keydown', function( e ) {
        focusInstance( THIS );
        keyControl( e );
      } );

      // keydown is before keypress and focuses already
      onOffEvent( _nodes.colorPicker, 'keypress', keyControl );
      // onOffEvent(_nodes.colorPicker, 'keyup', keyControl);

      onOffEvent( _nodes.colorPicker, 'paste', function( e ) {
        e.target.firstChild.data = e.clipboardData.getData( 'Text' );
        return preventDefault( e );
      } );
    }

    addEvent( _isIE ? document.body : window, 'mouseup', stopChange );

    // ------------------------------------------------------ //
    // --------- Event listner's callback functions  -------- //
    // -------------------------------------------------------//

    function stopChange( e, action ) {
      var mouseMoveAction = _mouseMoveAction;

      if ( _mouseMoveAction ) { // why??? please test again...
        // if (document.selection && _mouseMoveAction !== changeInputValue) {
        // 	//ie -> prevent showing the accelerator menu
        // 	document.selection.empty();
        // }
        window[ cancelAnimationFrame ]( _renderTimer );
        removeEvent( _isIE ? document.body : window, 'mousemove', _mouseMoveAction );
        if ( _delayState ) { // hapens on inputs
          _valueType = {
            type: 'alpha'
          };
          renderAll();
        }
        // this is dirty... has to do with M|W|! button
        if ( typeof _mouseMoveAction === 'function' || typeof _mouseMoveAction === 'number' ) {
          delete _options.webUnsave;
        }

        _delayState = 1;
        _mouseMoveAction = undefined;

        changeClass( _nodes.slds, 'do-drag', '' );
        changeClass( _nodes.panel, '(?:start-change|do-change)', '' );

        _nodes.resizer.style.cssText = '';
        _nodes.panelCover.style.cssText = '';

        _nodes.memo_store.style.cssText = 'background-color: ' +
          color2string( _colors.RND.rgb ) + '; ' + getOpacityCSS( _colors.alpha );
        _nodes.memo.className = _nodes.memo.className.replace( /\s+(?:dark|light)/, '' ) +
          // (/dark/.test(_nodes.colorPicker.className) ? ' dark' : ' light');
          ( _colors[ 'rgbaMix' + _bgTypes[ _options.alphaBG ] ].luminance < 0.22 ? ' dark' : ' light' );
        // (_colors.rgbaMixCustom.luminance < 0.22 ? ' dark' : ' light')

        _valueType = undefined;

        resetCursors();

        if ( _options.actionCallback ) {
          _options.actionCallback( e, _action || mouseMoveAction.name || action || 'external' );
        }
      }
    }

    function changeXYValue( e ) {
      var event = e || window.event,
        scale = _options.scale,
        page = getPageXY( event ),
        x = ( page.X - _targetOrigin.left ) * ( scale === 4 ? 2 : scale ),
        y = ( page.Y - _targetOrigin.top ) * scale,
        mode = _options.mode;

      _colors[ mode.type ][ mode.x ] = limitValue( x / 255, 0, 1 );
      _colors[ mode.type ][ mode.y ] = 1 - limitValue( y / 255, 0, 1 );
      convertColors();
      return preventDefault( event );
    }

    function changeZValue( e ) { // make this part of changeXYValue
      var event = e || window.event,
        page = getPageXY( event ),
        z = ( page.Y - _targetOrigin.top ) * _options.scale,
        mode = _options.mode;

      _colors[ mode.type ][ mode.z ] = 1 - limitValue( z / 255, 0, 1 );
      convertColors();
      return preventDefault( event );
    }

    function changeOpacityValue( e ) {
      var event = e || window.event,
        page = getPageXY( event );

      _newData = true;
      _colors.alpha = limitValue( _math.round(
        ( page.X - _targetOrigin.left ) / _targetOrigin.width * 100 ), 0, 100 ) / 100;
      convertColors( 'alpha' );
      return preventDefault( event );
    }

    function changeInputValue( e ) {
      var event = e || window.event,
        page = getPageXY( event ),
        delta = _startCoords.pageY - page.Y,
        delayOffset = _options.delayOffset,
        type = _valueType.type,
        isAlpha = type === 'alpha',
        ranges;

      if ( _delayState || _math.abs( delta ) >= delayOffset ) {
        if ( !_delayState ) {
          _delayState = ( delta > 0 ? -delayOffset : delayOffset ) +
            ( +_mainTarget.firstChild.data ) * ( isAlpha ? 100 : 1 );
          _startCoords.pageY += _delayState;
          delta += _delayState;
          _delayState = 1;
          changeClass( _nodes.panel, 'start-change', 'do-change' );
          _nodes.panelCover.style.cssText = 'position:absolute;left:0;top:0;right:0;bottom:0';
          // window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
          document.activeElement.blur();
          _renderTimer = window[ requestAnimationFrame ]( renderAll );
        }

        if ( type === 'cmyk' && _options.cmyOnly ) {
          type = 'cmy';
        }

        if ( isAlpha ) {
          _newData = true;
          _colors.alpha = limitValue( delta / 100, 0, 1 );
        } else {
          ranges = _valueRanges[ type ][ _valueType.z ];
          _colors[ type ][ _valueType.z ] = type === 'Lab' ? limitValue( delta, ranges[ 0 ], ranges[ 1 ] ) :
            limitValue( delta / ranges[ 1 ], 0, 1 );
        }
        convertColors( isAlpha ? 'alpha' : type );
        // event.returnValue is deprecated. Please use the standard event.preventDefault() instead.
        // event.returnValue = false; // see: pauseEvent(event);
        return preventDefault( event );
      }
    }

    function keyControl( e ) { // this is quite big for what it does...
      var event = e || window.event,
        keyCode = event.which || event.keyCode,
        key = String.fromCharCode( keyCode ),
        elm = document.activeElement,

        cln = elm.className.replace( _options.CSSPrefix, '' ).split( '-' ),
        type = cln[ 0 ],
        mode = cln[ 1 ],

        isAlpha = type === 'alpha',
        isHex = type === 'HEX',
        arrowKey = {
          k40: -1,
          k38: 1,
          k34: -10,
          k33: 10
        }[ 'k' + keyCode ] / ( isAlpha ? 100 : 1 ),
        validKeys = {
          'HEX': /[0-9a-fA-F]/,
          'Lab': /[\-0-9]/,
          'alpha': /[\.0-9]/
        }[ type ] || /[0-9]/,
        valueRange = _valueRanges[ type ][ type ] || _valueRanges[ type ][ mode ], // let op!

        textNode = elm.firstChild, // chnge on TAB key
        rangeData = caret( elm ),
        origValue = textNode.data, // do not change
        value,
        val = origValue === '0' && !isHex ? [] : origValue.split( '' ); // gefixt

      if ( /^(?:27|13)$/.test( keyCode ) ) { // ENTER || ESC
        preventDefault( event );
        elm.blur();
      } else if ( event.type === 'keydown' ) { // functional keys
        if ( arrowKey ) { // arrow/page keys
          value = limitValue( _math.round( ( +origValue + arrowKey ) * 1e+6 ) / 1e+6, valueRange[ 0 ], valueRange[ 1 ] );
        } else if ( /^(?:8|46)$/.test( keyCode ) ) { // DELETE / BACKSPACE
          if ( !rangeData.range ) {
            rangeData.range++;
            rangeData.start -= keyCode === 8 ? 1 : 0;
          }
          val.splice( rangeData.start, rangeData.range );
          value = val.join( '' ) || '0'; // never loose elm.firstChild
        }

        if ( value !== undefined ) { // prevent keypress
          preventDefault( event, true );
        }
      } else if ( event.type === 'keypress' ) {
        if ( !/^(?:37|39|8|46|9)$/.test( keyCode ) ) { // left, right,DEL, BACK, TAB for FF
          preventDefault( event, true );
        }
        if ( validKeys.test( key ) ) { // regular input
          val.splice( rangeData.start, rangeData.range, key );
          value = val.join( '' );
        }
        rangeData.start++;
      }

      if ( keyCode === 13 && isHex ) {
        if ( textNode.data.length % 3 === 0 || textNode.data === '0' ) { // textNode.data.length && 
          return _colorPicker.setColor( textNode.data === '0' ? '000' : textNode.data, 'rgb', _colors.alpha, true );
        } else {
          preventDefault( event, true );
          return elm.focus();
        }
      }

      if ( isHex && value !== undefined ) {
        value = /^0+/.test( value ) ? value : parseInt( '' + value, 16 ) || 0;
      }

      if ( value !== undefined && value !== '' && +value >= valueRange[ 0 ] && +value <= valueRange[ 1 ] ) {
        if ( isHex ) {
          value = value.toString( 16 ).toUpperCase() || '0';
        }
        if ( isAlpha ) {
          _colors[ type ] = +value;
        } else if ( !isHex ) {
          _colors[ type ][ mode ] = +value / ( type === 'Lab' ? 1 : valueRange[ 1 ] );
        }
        convertColors( isAlpha ? 'alpha' : type );

        preRenderAll( _colors );
        _mouseMoveAction = true;
        stopChange( e, event.type );

        textNode.data = value; // if 
        caret( elm, _math.min( elm.firstChild.data.length, rangeData.start < 0 ? 0 : rangeData.start ) );
      }
    }

    function buttonActions( e ) {
      var event = e || window.event,
        target = event.target || event.srcElement,
        targetClass = target.className,
        parent = target.parentNode,
        options = _options,
        RGB = _colors.RND.rgb,
        customBG, alphaBG,
        mode = _options.mode,
        newMode = '',
        prefix = options.CSSPrefix,
        isModeButton = /(?:hs|rgb)/.test( parent.className ) && /^[HSBLRG]$/.test(
          target.firstChild ? target.firstChild.data : ''
        ),
        isDblClick = /dblc/.test( event.type ),
        buttonAction = ''; // think this over again....

      if ( isDblClick && !isModeButton ) {
        return;
      } else if ( targetClass.indexOf( '-labl ' + prefix + 'labl' ) !== -1 ) { // HSB -> HSL; CMYK -> Lab buttons
        changeClass( _nodes[ targetClass.split( '-' )[ 0 ] ], prefix + 'hide', '' );
        changeClass( _nodes[ parent.className.split( '-' )[ 1 ] ], prefix + 'hide' );
      } else if ( targetClass.indexOf( prefix + 'butt' ) !== -1 ) { // BUTTONS
        if ( isModeButton ) { // set render modes
          if ( isDblClick && _options.scale === 2 ) {
            newMode = /hs/.test( mode.type ) ? 'rgb' : /hide/.test( _nodes.hsl.className ) ? 'hsv' : 'hsl';
            newMode = newMode + '-' + newMode[ mode.type.indexOf( mode.z ) ];
          }
          _colorPicker.setMode( newMode ? newMode : targetClass.replace( '-butt', '' ).split( ' ' )[ 0 ] );
          buttonAction = 'modeChange';
        } else if ( /^[rgb]/.test( targetClass ) ) { // no vertical slider rendering in RGB mode
          newMode = targetClass.split( '-' )[ 1 ];
          changeClass( _nodes.colorPicker, 'no-rgb-' + newMode,
            ( options[ 'noRGB' + newMode ] = !options[ 'noRGB' + newMode ] ) ? undefined : '' );
          buttonAction = 'noRGB' + newMode;
          // preRenderAll();
        } else if ( target === _nodes.alpha_labl ) { // alpha button right (background of raster)
          customBG = options.customBG;
          alphaBG = options.alphaBG;
          changeClass( _nodes.colorPicker, 'alpha-bg-' + alphaBG, 'alpha-bg-' +
            ( alphaBG = options.alphaBG = e.data || ( alphaBG === 'w' ? ( customBG ? 'c' : 'b' ) :
              alphaBG === 'c' ? 'b' : 'w' ) ) );
          target.firstChild.data = alphaBG.toUpperCase();
          _nodes.ctrl.style.backgroundColor = _nodes.memo.style.backgroundColor =
            alphaBG !== 'c' ? '' : 'rgb(' + _math.round( customBG.r * 255 ) + ', ' +
            _math.round( customBG.g * 255 ) + ', ' +
            _math.round( customBG.b * 255 ) + ')';
          _nodes.raster.style.cssText = _nodes.raster_bg.previousSibling.style.cssText =
            alphaBG !== 'c' ? '' : getOpacityCSS( customBG.luminance < 0.22 ? 0.5 : 0.4 );
          buttonAction = 'alphaBackground';
        } else if ( target === _nodes.alpha_butt ) { // alpha button left (disable alpha rendering)
          changeClass( _nodes.colorPicker, 'mute-alpha', ( options.muteAlpha = !options.muteAlpha ) ? undefined : '' );
          buttonAction = 'alphaState';
        } else if ( target === _nodes.HEX_butt ) { // make it on/off
          changeClass( _nodes.colorPicker, 'no-HEX', ( options.HEXState = !options.HEXState ) ? undefined : '' );
          buttonAction = 'HEXState';
        } else if ( target === _nodes.HEX_labl ) { // web save state change
          var isWebSave = _colors.saveColor === 'web save';

          if ( _colors.saveColor !== 'web smart' && !isWebSave ) {
            options.webUnsave = copyColor( RGB );
            _colorPicker.setColor( _colors.webSmart, 'rgb' );
          } else if ( !isWebSave ) {
            if ( !options.webUnsave ) {
              options.webUnsave = copyColor( RGB );
            }
            _colorPicker.setColor( _colors.webSave, 'rgb' );
          } else {
            _colorPicker.setColor( options.webUnsave, 'rgb' );
          }
          buttonAction = 'webColorState';
        } else if ( /Lab-x-labl/.test( targetClass ) ) { //target === _nodes.cmyk_type) {
          // switch between CMYK and CMY
          changeClass( _nodes.colorPicker, 'cmy-only', ( options.cmyOnly = !options.cmyOnly ) ? undefined : '' );
          buttonAction = 'cmykState';
        }
      } else if ( target === _nodes.bsav ) { // SAVE
        saveAsBackground();
        buttonAction = 'saveAsBackground';
      } else if ( target === _nodes.bres ) { // RESET
        var tmpColor = copyColor( RGB ),
          tmpAlpha = _colors.alpha;

        // a bit heavy but... doesn't matter here
        // newCol, type, alpha, forceRender
        _colorPicker.setColor( options.color );
        saveAsBackground();
        _colorPicker.setColor( tmpColor, 'rgb', tmpAlpha );
        buttonAction = 'resetColor';
      } else if ( parent === _nodes.col1 ) { // COLOR left
        // _colors.hsv.h = (_colors.hsv.h + 0.5) % 1; // not acurate
        _colors.hsv.h -= ( _colors.hsv.h > 0.5 ? 0.5 : -0.5 );
        convertColors( 'hsv' );
        buttonAction = 'shiftColor';

      } else if ( parent === _nodes.col2 ) { // COLOR right
        _colorPicker.setColor( target.style.backgroundColor, 'rgb', _colors.background.alpha );
        buttonAction = 'setSavedColor';
      } else if ( parent === _nodes.memo ) { // MEMORIES // revisit...
        var resetBlink = function() {
            if ( _nodes.memos.blinker ) _nodes.memos.blinker.style.cssText = _nodes.memos.cssText;
          },
          doBlink = function( elm ) {
            _nodes.memos.blinker = elm;
            elm.style.cssText = 'background-color:' + ( _colors.RGBLuminance > 0.22 ? '#333' : '#DDD' );
            window.setTimeout( resetBlink, 200 );
          };

        if ( target === _nodes.memo_cursor ) { // save color in memo
          resetBlink();
          _nodes.memos.blinker = undefined;
          _nodes.testNode.style.cssText = _nodes.memo_store.style.cssText;
          _nodes.memos.cssText = _nodes.testNode.style.cssText; // ...how browser sees css
          for ( var n = _nodes.memos.length - 1; n--; ) { // check if color already exists
            if ( _nodes.memos.cssText === _nodes.memos[ n ].style.cssText ) {
              doBlink( _nodes.memos[ n ] ); // sets _nodes.memos.blinker
              break;
            }
          }
          if ( !_nodes.memos.blinker ) { // right shift colors
            for ( var n = _nodes.memos.length - 1; n--; ) {
              _nodes.memos[ n + 1 ].style.cssText = _nodes.memos[ n ].style.cssText;
            }
            _nodes.memos[ 0 ].style.cssText = _nodes.memo_store.style.cssText;
          }
          buttonAction = 'toMemory';
        } else { // reset color from memo
          resetBlink();
          _colorPicker.setColor( target.style.backgroundColor, 'rgb', target.style.opacity || 1 );
          _nodes.memos.cssText = target.style.cssText;
          doBlink( target );
          // this is dirty... has to do with M|W|! button
          _mouseMoveAction = 1;
          buttonAction = 'fromMemory';
        }

      }
      // think this over again, does this need to be like this??
      if ( buttonAction ) {
        preRenderAll( _colors );
        _mouseMoveAction = _mouseMoveAction ||  true; // !!!! search for: // this is dirty...
        stopChange( e, buttonAction );
      }
    }

    function resizeApp( e, size ) {
      var event = e || window.event,
        page = event ? getPageXY( event ) : {},
        isSize = size !== undefined,
        x = isSize ? size : page.X - _targetOrigin.left + 8,
        y = isSize ? size : page.Y - _targetOrigin.top + 8,
        values = [ ' S XS XXS', ' S XS', ' S', '' ],
        sizes = _options.sizes, // from getUISizes();
        currentSize = isSize ? size :
        y < sizes.XXS[ 1 ] + 25 ? 0 :
        x < sizes.XS[ 0 ] + 25 ? 1 :
        x < sizes.S[ 0 ] + 25 || y < sizes.S[ 1 ] + 25 ? 2 : 3,
        value = values[ currentSize ],
        isXXS = false,
        mode,
        tmp = '';

      if ( _cashedVars.resizer !== value ) {
        isXXS = /XX/.test( value );
        mode = _options.mode;

        if ( isXXS && ( !/hs/.test( mode.type ) || mode.z === 'h' ) ) {
          tmp = mode.type + '-' + mode.z;
          _colorPicker.setMode( /hs/.test( mode.type ) ? mode.type + '-s' : 'hsv-s' );
          _options.mode.original = tmp;
        } else if ( mode.original ) {
          // setMode(mode) creates a new object so mode.original gets deleted automatically
          _colorPicker.setMode( mode.original );
        }

        _nodes.colorPicker.className = _nodes.colorPicker.className.replace( /\s+(?:S|XS|XXS)/g, '' ) + value;
        _options.scale = isXXS ? 4 : /S/.test( value ) ? 2 : 1;
        _options.currentSize = currentSize;

        _cashedVars.resizer = value;

        // fix this... from this point on inside if() ... convertColors();
        _newData = true;
        renderAll();
        resetCursors();
      }

      _nodes.resizer.style.cssText = 'display: block;' +
        'width: ' + ( x > 10 ? x : 10 ) + 'px;' +
        'height: ' + ( y > 10 ? y : 10 ) + 'px;';
    }

    // ------------------------------------------------------ //
    // --- Colors calculation and rendering related stuff  --- //
    // -------------------------------------------------------//

    function setMode( mode ) {
      var ModeMatrix = {
          rgb_r: {
            x: 'b',
            y: 'g'
          },
          rgb_g: {
            x: 'b',
            y: 'r'
          },
          rgb_b: {
            x: 'r',
            y: 'g'
          },

          hsv_h: {
            x: 's',
            y: 'v'
          },
          hsv_s: {
            x: 'h',
            y: 'v'
          },
          hsv_v: {
            x: 'h',
            y: 's'
          },

          hsl_h: {
            x: 's',
            y: 'l'
          },
          hsl_s: {
            x: 'h',
            y: 'l'
          },
          hsl_l: {
            x: 'h',
            y: 's'
          }
        },
        key = mode.replace( '-', '_' ),
        regex = '\\b(?:rg|hs)\\w\\-\\w\\b'; // \\b\\w{3}\\-\\w\\b';

      // changeClass(_nodes.colorPicker, '(?:.*?)$', mode);
      // changeClass(_nodes.colorPicker, '\\b\\w{3}\\-\\w\\b', mode);
      // changeClass(_nodes.slds, '\\b\\w{3}\\-\\w\\b', mode);
      changeClass( _nodes.panel, regex, mode );
      changeClass( _nodes.slds, regex, mode );

      mode = mode.split( '-' );
      return _options.mode = {
        type: mode[ 0 ],
        x: ModeMatrix[ key ].x,
        y: ModeMatrix[ key ].y,
        z: mode[ 1 ]
      };
    }

    function initSliders() { // function name...
      var regex = /\s+(?:hue-)*(?:dark|light)/g,
        className = 'className'; // minification

      _nodes.curl[ className ] = _nodes.curl[ className ].replace( regex, '' ); // .....
      _nodes.curr[ className ] = _nodes.curr[ className ].replace( regex, '' ); // .....
      _nodes.slds[ className ] = _nodes.slds[ className ].replace( regex, '' );
      // var sldrs = ['sldr_2', 'sldr_4', 'sldl_3'];
      // for (var n = sldrs.length; n--; ) {
      // 	_nodes[sldrs[n]][className] = _options.CSSPrefix + sldrs[n].replace('_', '-');
      // }
      _nodes.sldr_2[ className ] = _options.CSSPrefix + 'sldr-2';
      _nodes.sldr_4[ className ] = _options.CSSPrefix + 'sldr-4';
      _nodes.sldl_3[ className ] = _options.CSSPrefix + 'sldl-3';

      for ( var style in _nodes.styles ) {
        if ( !style.indexOf( 'sld' ) ) _nodes.styles[ style ].cssText = '';
      }
      _cashedVars = {};
    }

    function resetCursors() {
      // _renderVars.isNoRGB = undefined;
      _nodes.styles.curr.cssText = _nodes.styles.curl.cssText; // only coordinates
      _nodes.curl.className = _options.CSSPrefix + 'curl' + (
        _renderVars.noRGBZ ? ' ' + _options.CSSPrefix + 'curl-' + _renderVars.noRGBZ : '' );
      _nodes.curr.className = _options.CSSPrefix + 'curr ' + _options.CSSPrefix + 'curr-' +
        ( _options.mode.z === 'h' ? _renderVars.HUEContrast : _renderVars.noRGBZ ?
          _renderVars.noRGBZ : _renderVars.RGBLuminance );
    }

    function convertColors( type ) {
      preRenderAll( _colorInstance.setColor( undefined, type || _options.mode.type ) );
      _newData = true;
    }

    function saveAsBackground( refresh ) {
      _colorInstance.saveAsBackground();
      _nodes.styles.col2.cssText = 'background-color: ' + color2string( _colors.background.RGB ) + ';' +
        getOpacityCSS( _colors.background.alpha );

      if ( refresh ) {
        preRenderAll( _colors );
        // renderAll();
      }
      return ( _colors );
    }

    function preRenderAll( colors ) {
      var _Math = _math,
        renderVars = _renderVars,
        bgType = _bgTypes[ _options.alphaBG ];

      renderVars.hueDelta = _Math.round( colors[ 'rgbaMixBGMix' + bgType ].hueDelta * 100 );
      // renderVars.RGBLuminanceDelta = _Math.round(colors.RGBLuminanceDelta * 100);
      renderVars.luminanceDelta = _Math.round( colors[ 'rgbaMixBGMix' + bgType ].luminanceDelta * 100 );
      renderVars.RGBLuminance = colors.RGBLuminance > 0.22 ? 'light' : 'dark';
      renderVars.HUEContrast = colors.HUELuminance > 0.22 ? 'light' : 'dark';
      // renderVars.contrast = renderVars.RGBLuminanceDelta > renderVars.hueDelta ? 'contrast' : '';
      renderVars.contrast = renderVars.luminanceDelta > renderVars.hueDelta ? 'contrast' : '';
      renderVars.readabiltiy =
        colors[ 'rgbaMixBGMix' + bgType ].WCAG2Ratio >= 7 ? 'green' :
        colors[ 'rgbaMixBGMix' + bgType ].WCAG2Ratio >= 4.5 ? 'orange' : '';
      renderVars.noRGBZ = _options[ 'no' + _options.mode.type.toUpperCase() + _options.mode.z ] ?
        ( _options.mode.z === 'g' && colors.rgb.g < 0.59 || _options.mode.z === 'b' ||  _options.mode.z === 'r' ?
          'dark' : 'light' ) : undefined;
    }

    function renderAll() { // maybe render alpha seperately...
      if ( _mouseMoveAction ) {
        // _renderTimer = window[requestAnimationFrame](renderAll);
        if ( !_newData ) return ( _renderTimer = window[ requestAnimationFrame ]( renderAll ) );
        _newData = false;
      }
      // console.time('renderAll');
      var options = _options,
        mode = options.mode,
        scale = options.scale,
        prefix = options.CSSPrefix,
        colors = _colors,
        nodes = _nodes,
        CSS = nodes.styles,
        textNodes = nodes.textNodes,
        valueRanges = _valueRanges,
        valueType = _valueType,
        renderVars = _renderVars,
        cashedVars = _cashedVars,

        _Math = _math,
        _getOpacityCSS = getOpacityCSS,
        _color2string = color2string,

        a = 0,
        b = 0,
        x = colors[ mode.type ][ mode.x ],
        X = _Math.round( x * 255 / ( scale === 4 ? 2 : scale ) ),
        y_ = colors[ mode.type ][ mode.y ],
        y = 1 - y_,
        Y = _Math.round( y * 255 / scale ),
        z = 1 - colors[ mode.type ][ mode.z ],
        Z = _Math.round( z * 255 / scale ),
        coords = ( 1 === 1 ) ? [ x, y_ ] : [ 0, 0 ], // (1 === 2) button label up

        isRGB = mode.type === 'rgb',
        isHue = mode.z === 'h',
        isHSL = mode.type === 'hsl',
        isHSL_S = isHSL && mode.z === 's',
        moveXY = _mouseMoveAction === changeXYValue,
        moveZ = _mouseMoveAction === changeZValue,
        display, tmp, value, slider;

      if ( isRGB ) {
        if ( coords[ 0 ] >= coords[ 1 ] ) b = 1;
        else a = 1;
        if ( cashedVars.sliderSwap !== a ) {
          nodes.sldr_2.className = options.CSSPrefix + 'sldr-' + ( 3 - a );
          cashedVars.sliderSwap = a;
        }
      }
      if ( ( isRGB && !moveZ ) || ( isHue && !moveXY ) || ( !isHue && !moveZ ) ) {
        CSS[ isHue ? 'sldl_2' : 'sldr_2' ][ isRGB ? 'cssText' : 'backgroundColor' ] =
          isRGB ? _getOpacityCSS( ( coords[ a ] - coords[ b ] ) / ( 1 - ( coords[ b ] ) || 0 ) ) : _color2string( colors.hueRGB );
      }
      if ( !isHue ) {
        if ( !moveZ ) CSS.sldr_4.cssText = _getOpacityCSS( isRGB ? coords[ b ] : isHSL_S ? _Math.abs( 1 - y * 2 ) : y );
        if ( !moveXY ) CSS.sldl_3.cssText = _getOpacityCSS( isHSL && mode.z === 'l' ? _Math.abs( 1 - z * 2 ) : z );
        if ( isHSL ) { // switch slider class name for black/white color half way through in HSL(S|L) mode(s)
          slider = isHSL_S ? 'sldr_4' : 'sldl_3';
          tmp = isHSL_S ? 'r-' : 'l-';
          value = isHSL_S ? ( y > 0.5 ? 4 : 3 ) : ( z > 0.5 ? 3 : 4 );

          if ( cashedVars[ slider ] !== value ) {
            nodes[ slider ].className = options.CSSPrefix + 'sld' + tmp + value;
            cashedVars[ slider ] = value;
          }
        }
      }

      if ( !moveZ ) CSS.curm.cssText = 'left: ' + X + 'px; top: ' + Y + 'px;';
      if ( !moveXY ) CSS.curl.top = Z + 'px';
      if ( valueType ) CSS.curr.top = Z + 'px'; // && valueType.type !== mode.type
      if ( ( valueType && valueType.type === 'alpha' ) || _mainTarget === nodes.opacity ) {
        CSS.opacity_slider.left = options.opacityPositionRelative ? ( colors.alpha * (
            ( _targetOrigin.width || nodes.opacity.offsetWidth ) -
            ( _targetOrigin.childWidth || nodes.opacity_slider.offsetWidth ) ) ) + 'px' :
          ( colors.alpha * 100 ) + '%';
      }

      CSS.col1.cssText = 'background-color: ' + _color2string( colors.RND.rgb ) + '; ' +
        ( options.muteAlpha ? '' : _getOpacityCSS( colors.alpha ) );
      CSS.opacity.backgroundColor = _color2string( colors.RND.rgb );
      CSS.cold.width = renderVars.hueDelta + '%';
      CSS.cont.width = renderVars.luminanceDelta + '%';

      for ( display in textNodes ) {
        tmp = display.split( '_' );
        if ( options.cmyOnly ) {
          tmp[ 0 ] = tmp[ 0 ].replace( 'k', '' );
        }
        value = tmp[ 1 ] ? colors.RND[ tmp[ 0 ] ][ tmp[ 1 ] ] : colors.RND[ tmp[ 0 ] ] || colors[ tmp[ 0 ] ];
        if ( cashedVars[ display ] !== value ) {
          cashedVars[ display ] = value;
          textNodes[ display ].data = value > 359.5 && display !== 'HEX' ? 0 : value;

          if ( display !== 'HEX' && !options.noRangeBackground ) {
            value = colors[ tmp[ 0 ] ][ tmp[ 1 ] ] !== undefined ? colors[ tmp[ 0 ] ][ tmp[ 1 ] ] : colors[ tmp[ 0 ] ];
            if ( tmp[ 0 ] === 'Lab' ) {
              value = ( value - valueRanges[ tmp[ 0 ] ][ tmp[ 1 ] ][ 0 ] ) /
                ( valueRanges[ tmp[ 0 ] ][ tmp[ 1 ] ][ 1 ] - valueRanges[ tmp[ 0 ] ][ tmp[ 1 ] ][ 0 ] );
            }
            CSS[ display ].backgroundPosition = _Math.round( ( 1 - value ) * 100 ) + '% 0%';
          }
        }
      }
      // Lab out of gammut
      tmp = colors._rgb ? [
        colors._rgb.r !== colors.rgb.r,
        colors._rgb.g !== colors.rgb.g,
        colors._rgb.b !== colors.rgb.b
      ] : [];
      if ( tmp.join( '' ) !== cashedVars.outOfGammut ) {
        nodes.rgb_r_labl.firstChild.data = tmp[ 0 ] ? '!' : ' ';
        nodes.rgb_g_labl.firstChild.data = tmp[ 1 ] ? '!' : ' ';
        nodes.rgb_b_labl.firstChild.data = tmp[ 2 ] ? '!' : ' ';
        cashedVars.outOfGammut = tmp.join( '' );
      }
      if ( renderVars.noRGBZ ) {
        if ( cashedVars.noRGBZ !== renderVars.noRGBZ ) {
          nodes.curl.className = prefix + 'curl ' + prefix + 'curl-' + renderVars.noRGBZ;

          if ( !moveZ ) {
            nodes.curr.className = prefix + 'curr ' + prefix + 'curr-' + renderVars.noRGBZ;
          }
          cashedVars.noRGBZ = renderVars.noRGBZ;
        }
      }
      if ( cashedVars.HUEContrast !== renderVars.HUEContrast && mode.z === 'h' ) {
        nodes.slds.className = nodes.slds.className.replace( /\s+hue-(?:dark|light)/, '' ) +
          ' hue-' + renderVars.HUEContrast;
        if ( !moveZ ) {
          nodes.curr.className = prefix + 'curr ' + prefix + 'curr-' + renderVars.HUEContrast;
        }
        cashedVars.HUEContrast = renderVars.HUEContrast;
      } else if ( cashedVars.RGBLuminance !== renderVars.RGBLuminance ) { // test for no else
        nodes.colorPicker.className = nodes.colorPicker.className.replace( /\s+(?:dark|light)/, '' ) +
          ' ' + renderVars.RGBLuminance;
        if ( !moveZ && mode.z !== 'h' && !renderVars.noRGBZ ) {
          nodes.curr.className = prefix + 'curr ' + prefix + 'curr-' + renderVars.RGBLuminance;
        }
        cashedVars.RGBLuminance = renderVars.RGBLuminance;
      }

      if ( cashedVars.contrast !== renderVars.contrast || cashedVars.readabiltiy !== renderVars.readabiltiy ) {
        nodes.ctrl.className = nodes.ctrl.className.replace( ' contrast', '' ).replace( /\s*(?:orange|green)/, '' ) +
          ( renderVars.contrast ? ' ' + renderVars.contrast : '' ) +
          ( renderVars.readabiltiy ? ' ' + renderVars.readabiltiy : '' );
        cashedVars.contrast = renderVars.contrast;
        cashedVars.readabiltiy = renderVars.readabiltiy;
      }

      if ( cashedVars.saveColor !== colors.saveColor ) {
        nodes.HEX_labl.firstChild.data = !colors.saveColor ? '!' : colors.saveColor === 'web save' ? 'W' : 'M';
        cashedVars.saveColor = colors.saveColor;
      }

      if ( options.renderCallback ) {
        options.renderCallback( colors, mode ); // maybe more parameters
      }

      if ( _mouseMoveAction ) {
        _renderTimer = window[ requestAnimationFrame ]( renderAll );
      }

      // console.timeEnd('renderAll')
    }


    // ------------------------------------------------------ //
    // ------------------ helper functions ------------------ //
    // -------------------------------------------------------//

    function copyColor( color ) {
      var newColor = {};

      for ( var n in color ) {
        newColor[ n ] = color[ n ];
      }
      return newColor;
    }

    // function color2string(color, type) {
    // 	var out = [],
    // 		n = 0;

    // 	type = type || 'rgb';
    // 	while (type.charAt(n)) { // IE7 // V8 type[n] || 
    // 		out.push(color[type.charAt(n)]);
    // 		n++;
    // 	}
    // 	return type + '(' + out.join(', ') + ')';
    // }

    function color2string( color, type ) { // ~2 x faster on V8
      var out = '',
        t = ( type || 'rgb' ).split( '' ),
        n = t.length;

      for ( ; n--; ) {
        out = ', ' + color[ t[ n ] ] + out;
      }
      return ( type || 'rgb' ) + '(' + out.substr( 2 ) + ')';
    }


    function limitValue( value, min, max ) {
      // return Math.max(min, Math.min(max, value)); // faster??
      return ( value > max ? max : value < min ? min : value );
    }

    function getOpacityCSS( value ) {
      if ( value === undefined ) value = 1;

      if ( _doesOpacity ) {
        return 'opacity: ' + ( _math.round( value * 10000000000 ) / 10000000000 ) + ';'; // value.toFixed(16) = 99% slower
        // some speed test:
        // return ['opacity: ', (Math.round(value * 1e+10) / 1e+10), ';'].join('');
      } else {
        return 'filter: alpha(opacity=' + _math.round( value * 100 ) + ');';
      }
    }

    function preventDefault( e, skip ) {
      e.preventDefault ? e.preventDefault() : e.returnValue = false;
      if ( !skip ) window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
      return false;
    }

    function changeClass( elm, cln, newCln ) {
      return !elm ? false : elm.className = ( newCln !== undefined ?
        elm.className.replace( new RegExp( '\\s+?' + cln, 'g' ), newCln ? ' ' + newCln : '' ) :
        elm.className + ' ' + cln );
    }

    function getOrigin( elm ) {
      var box = ( elm.getBoundingClientRect ) ? elm.getBoundingClientRect() : {
          top: 0,
          left: 0
        },
        doc = elm && elm.ownerDocument,
        body = doc.body,
        win = doc.defaultView || doc.parentWindow || window,
        docElem = doc.documentElement || body.parentNode,
        clientTop = docElem.clientTop || body.clientTop || 0, // border on html or body or both
        clientLeft = docElem.clientLeft || body.clientLeft || 0;

      return {
        left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - clientLeft,
        top: box.top + ( win.pageYOffset || docElem.scrollTop ) - clientTop
      };
    }

    function getPageXY( e ) {
      var doc = window.document;

      return {
        X: e.pageX || e.clientX + doc.body.scrollLeft + doc.documentElement.scrollLeft,
        Y: e.pageY || e.clientY + doc.body.scrollTop + doc.documentElement.scrollTop
      };
    }

    function addEvent( obj, type, func ) {
      addEvent.cache = addEvent.cache ||  {
        _get: function( obj, type, func, checkOnly ) {
          var cache = addEvent.cache[ type ] || [];

          for ( var n = cache.length; n--; ) {
            if ( obj === cache[ n ].obj && '' + func === '' + cache[ n ].func ) {
              func = cache[ n ].func;
              if ( !checkOnly ) {
                cache[ n ] = cache[ n ].obj = cache[ n ].func = null;
                cache.splice( n, 1 );
              }
              return func;
            }
          }
        },
        _set: function( obj, type, func ) {
          var cache = addEvent.cache[ type ] = addEvent.cache[ type ] || [];

          if ( addEvent.cache._get( obj, type, func, true ) ) {
            return true;
          } else {
            cache.push( {
              func: func,
              obj: obj
            } );
          }
        }
      };

      if ( !func.name && addEvent.cache._set( obj, type, func ) || typeof func !== 'function' ) {
        return;
      }

      if ( obj.addEventListener ) obj.addEventListener( type, func, false );
      else obj.attachEvent( 'on' + type, func );
    }

    function removeEvent( obj, type, func ) {
      if ( typeof func !== 'function' ) return;
      if ( !func.name ) {
        func = addEvent.cache._get( obj, type, func ) || func;
      }

      if ( obj.removeEventListener ) obj.removeEventListener( type, func, false );
      else obj.detachEvent( 'on' + type, func );
    }

    function caret( target, pos ) { // only for contenteditable
      var out = {};

      if ( pos === undefined ) { // get
        if ( window.getSelection ) { // HTML5
          target.focus();
          var range1 = window.getSelection().getRangeAt( 0 ),
            range2 = range1.cloneRange();
          range2.selectNodeContents( target );
          range2.setEnd( range1.endContainer, range1.endOffset );
          out = {
            end: range2.toString().length,
            range: range1.toString().length
          };
        } else { // IE < 9
          target.focus();
          var range1 = document.selection.createRange(),
            range2 = document.body.createTextRange();
          range2.moveToElementText( target );
          range2.setEndPoint( 'EndToEnd', range1 );
          out = {
            end: range2.text.length,
            range: range1.text.length
          };
        }
        out.start = out.end - out.range;
        return out;
      }
      // set
      if ( pos == -1 ) pos = target[ 'text' ]().length;

      if ( window.getSelection ) { // HTML5
        target.focus();
        window.getSelection().collapse( target.firstChild, pos );
      } else { // IE < 9
        var range = document.body.createTextRange();
        range.moveToElementText( target );
        range.moveStart( 'character', pos );
        range.collapse( true );
        range.select();
      }
      return pos;
    }

    // ------------- requestAnimationFrame shim ------------- //
    // ---------- quite optimized for minification ---------- //

    for ( var n = vendors.length; n-- && !window[ requestAnimationFrame ]; ) {
      window[ requestAnimationFrame ] = window[ vendors[ n ] + 'Request' + animationFrame ];
      window[ cancelAnimationFrame ] = window[ vendors[ n ] + 'Cancel' + animationFrame ] ||
        window[ vendors[ n ] + 'CancelRequest' + animationFrame ];
    }

    window[ requestAnimationFrame ] = window[ requestAnimationFrame ] || function( callback ) {
      // this is good enough... and better than setTimeout
      return window.setTimeout( callback, 1000 / _options.fps );
      // return _renderTimer ? _renderTimer : window.setInterval(callback, 1000 / _options.fps);
    };

    window[ cancelAnimationFrame ] = window[ cancelAnimationFrame ] || function( id ) {
      // console.log('OFF-', id + '-' + _renderTimer)
      window.clearTimeout( id );
      return _renderTimer = null;
    };

  } )( window );

  ( function( $, window ) {
    $.fn.extend( {
      colorPicker: function( config ) {
        var renderCallback = function( colors, mode ) {
            var options = this,
              $input = $( options.input ),
              $patch = $( options.patch ),
              RGB = colors.RND.rgb,
              HSL = colors.RND.hsl,
              AHEX = options.isIE8 ? ( colors.alpha < 0.16 ? '0' : '' ) +
              ( Math.round( colors.alpha * 100 ) ).toString( 16 ).toUpperCase() + colors.HEX : '',
              isAlpha = colors.alpha !== 1 && !options.isIE8,
              colorMode = $input.data( 'colorMode' );

            if ( !options._instance ) return;

            $patch.css( {
              'color': ( colors.rgbaMixCustom.luminance > 0.22 ? '#222' : '#ddd' ), // Black...???
              'background-color': options._instance.toString(),
              'filter': ( options.isIE8 ? 'progid:DXImageTransform.Microsoft.gradient(' + // IE<9
                'startColorstr=#' + AHEX + ',' + 'endColorstr=#' + AHEX + ')' : '' )
            } );

            $input.val( colorMode === 'HEX' && !isAlpha ? '#' + ( options.isIE8 ? AHEX : colors.HEX ) :
              options._instance.toString( colorMode, options.forceAlpha )
            );

            if ( options.displayCallback ) {
              options.displayCallback( colors, mode, options );
            }
          },
          extractValue = function( elm ) {
            return elm.value || elm.getAttribute( 'value' ) || elm.style.backgroundColor || '#FFFFFF';
          },
          actionCallback = function( event, action ) {
            var options = this,
              colorPicker = colorPickers.current;

            if ( action === 'toMemory' ) {
              var memos = colorPicker.nodes.memos,
                $memo,
                backgroundColor = '',
                opacity = 0,
                cookieTXT = [];

              for ( var n = 0, m = memos.length; n < m; n++ ) {
                $memo = $( memos[ n ] );
                backgroundColor = $memo.css( 'background-color' );
                opacity = Math.round( $memo.css( 'opacity' ) * 100 ) / 100;
                cookieTXT.push( backgroundColor.replace( /, /g, ',' ).replace( 'rgb(', 'rgba(' ).replace( ')', ',' + opacity + ')' ) );
              }
              cookieTXT = '\'' + cookieTXT.join( '\',\'' ) + '\'';
              $.docCookies( 'colorPickerMemos' + ( options.noAlpha ? 'NoAlpha' : '' ), cookieTXT );
            } else if ( action === 'resizeApp' ) {
              $.docCookies( 'colorPickerSize', colorPicker.color.options.currentSize );
            } else if ( action === 'modeChange' ) {
              var mode = colorPicker.color.options.mode;

              $.docCookies( 'colorPickerMode', mode.type + '-' + mode.z );
            }
          },
          createInstance = function( elm, config ) {
            var initConfig = {
                klass: window.ColorPicker,
                input: elm,
                patch: elm,
                isIE8: !!document.all && !document.addEventListener, // Opera???
                animationSpeed: 200,
                draggable: true,
                margin: {
                  left: -1,
                  top: 2
                },
                customBG: '#FFFFFF',
                // displayCallback: displayCallback,
                /* --- regular colorPicker options from this point --- */
                color: extractValue( elm ),
                initStyle: 'display: none',
                mode: $.docCookies( 'colorPickerMode' ) || 'hsv-h',
                // memoryColors: (function(colors, config) {
                // 	return config.noAlpha ?
                // 		colors.replace(/\,\d*\.*\d*\)/g, ',1)') : colors;
                // })($.docCookies('colorPickerMemos'), config || {}),
                // forceAlpha: true,
                memoryColors: $.docCookies( 'colorPickerMemos' + ( ( config || {} ).noAlpha ? 'NoAlpha' : '' ) ),
                size: $.docCookies( 'colorPickerSize' ) || 1,
                renderCallback: renderCallback,
                actionCallback: actionCallback
              },
              instance;

            for ( var n in config ) {
              initConfig[ n ] = config[ n ];
            }
            instance = new initConfig.klass( initConfig );
            instance.color.options._instance = instance.color;
            return instance;
          },
          doEventListeners = function( elm, multiple, off ) {
            var onOff = off ? 'off' : 'on';

            $( elm )[ onOff ]( 'focus.colorPicker', function( e ) {
              var $input = $( this ),
                position = $input.offset(),
                index = multiple ? $( that ).index( this ) : 0,
                colorPicker = colorPickers[ index ] ||
                ( colorPickers[ index ] = createInstance( this, config ) ),
                options = colorPicker.color.options,
                $colorPicker = $.ui && options.draggable ?
                $( colorPicker.nodes.colorPicker ).draggable( {
                  cancel: '.' + options.CSSPrefix + 'app div'
                } ) : $( colorPicker.nodes.colorPicker ),
                $appendTo = $( options.appendTo || document.body ),
                isStatic = /static/.test( $appendTo.css( 'position' ) ),
                atrect = isStatic ? {
                  left: 0,
                  top: 0
                } : $appendTo[ 0 ].getBoundingClientRect(),
                waitTimer = 0;

              options.color = extractValue( elm ); // brings color to default on reset
              $colorPicker.css( {
                'position': 'absolute',
                'left': position.left + options.margin.left - atrect.left,
                'top': position.top + $input.outerHeight( true ) + options.margin.top - atrect.top
              } );
              if ( !multiple ) {
                options.input = elm;
                options.patch = elm; // check again???
                colorPicker.setColor( extractValue( elm ), undefined, undefined, true );
                colorPicker.saveAsBackground();
              }
              colorPickers.current = colorPickers[ index ];
              $appendTo.append( $colorPicker );
              waitTimer = setInterval( function() { // compensating late style on onload in colorPicker
                if ( colorPickers.current.cssIsReady ) {
                  waitTimer = clearInterval( waitTimer );
                  $colorPicker.show( colorPicker.color.options.animationSpeed );
                }
              }, 10 );

            } );

            $( window )[ onOff ]( 'mousedown.colorPicker', function( e ) {
              var colorPicker = colorPickers.current,
                $colorPicker = $( colorPicker ? colorPicker.nodes.colorPicker : undefined ),
                animationSpeed = colorPicker ? colorPicker.color.options.animationSpeed : 0,
                isColorPicker = $( e.target ).closest( '.cp-app' )[ 0 ],
                inputIndex = $( that ).index( e.target );

              if ( isColorPicker && colorPicker && $( colorPickers ).index( isColorPicker ) ) {
                if ( e.target === colorPicker.nodes.exit ) {
                  $colorPicker.hide( animationSpeed );
                  $( ':focus' ).trigger( 'blur' );
                } else {
                  // buttons on colorPicker don't work any more
                  // $(document.body).append(isColorPicker);
                }
              } else if ( inputIndex !== -1 ) {
                // input fireld
              } else {
                $colorPicker.hide( animationSpeed );
              }
            } );
          },
          that = this,
          colorPickers = $.fn.colorPicker.colorPickers || [], // this is a way to prevent data binding on HTMLElements
          testColors = new window.Colors( {
            customBG: ( config && config.customBG ) || '#FFFFFF',
            allMixDetails: true
          } );

        $.fn.colorPicker.colorPickers = colorPickers;

        $( this ).each( function( idx, elm ) {
          // doEventListeners(elm, (config && config.multipleInstances), true);
          $( elm ).off( '.colorPicker' );
          $( window ).off( '.colorPicker' );
          if ( config !== 'destroy' ) {
            var color = extractValue( elm ),
              value = color.split( '(' );
            $( elm ).data( 'colorMode', value[ 1 ] ? value[ 0 ].substr( 0, 3 ) : 'HEX' );
            doEventListeners( elm, ( config && config.multipleInstances ), false );
            if ( config && config.readOnly ) {
              elm.readOnly = true;
            }
            testColors.setColor( color );
            if ( config && config.init ) {
              config.init( elm, testColors.colors );
            }
          }
        } );

        return this;
      }
    } );

    $.docCookies = function( key, val, options ) {
      var encode = encodeURIComponent,
        decode = decodeURIComponent,
        cookies, n, tmp, cache = {},
        days;

      if ( val === undefined ) { // all about reading cookies
        cookies = document.cookie.split( '; ' ) || []; // easier for decoding then with RegExp search // .split(/;\s*/)
        for ( n = cookies.length; n--; ) {
          tmp = cookies[ n ].split( '=' );
          if ( tmp[ 0 ] ) cache[ decode( tmp.shift() ) ] = decode( tmp.join( '=' ) ); // there might be '='s in the value...
        }

        if ( !key ) return cache; // return Json for easy access to all cookies
        else return cache[ key ]; // easy access to cookies from here
      } else { // write/delete cookie
        options = options || {};

        if ( val === '' || options.expires < 0 ) { // prepare deleteing the cookie
          options.expires = -1;
          // options.path = options.domain = options.secure = undefined; // to make shure the cookie gets deleted...
        }

        if ( options.expires !== undefined ) { // prepare date if any
          days = new Date();
          days.setDate( days.getDate() + options.expires );
        }

        document.cookie = encode( key ) + '=' + encode( val ) +
          ( days ? '; expires=' + days.toUTCString() : '' ) +
          ( options.path ? '; path=' + options.path : '' ) +
          ( options.domain ? '; domain=' + options.domain : '' ) +
          ( options.secure ? '; secure' : '' );
      }
    };
  } )( jQuery, window );



  //=====================colorPicker  end=========================


  var publishController = {
    _crontroller: 'questions',
    dialogid: null,
    overlays: {},
    loading_html: '<img src="/img/ajax/wheel_throbber.gif"> 正在加载...',
    open_dialog: function( url, options, postdata ) {
      var $dialog = this;
      $dialog.loading_html = '<img src="' + BASEURL + '/img/ajax/wheel_throbber.gif"> 正在加载...';
      var lastid = $dialog.dialogid;
      if ( options.id ) {
        $dialog.dialogid = options.id;
      } else {
        $dialog.dialogid = url.replace( /\/|\.|:|,| |\{|\}|\]|\[|\"|\'|\?|=|&/g, '_' ) + '-ajax—action';
      }

      function dialog_loaded() {
        $( '.nav-tabs a', '#' + $dialog.dialogid ).click( function( e ) {
          e.preventDefault();
          $( this ).blur();
          $( this ).tab( 'show' );
        } );
        $( '.nav-tabs a:first', '#' + $dialog.dialogid ).tab( 'show' );
        $( '.dropdown-toggle', '#' + $dialog.dialogid ).dropdown();
        $( 'button', '#' + $dialog.dialogid ).addClass( 'btn' );
        if ( typeof( options.callback ) == 'function' ) {
          options.callback( $( '#' + $dialog.dialogid ) );
        }
        $( '#' + $dialog.dialogid ).find( 'form' ).each( function() {
          if ( typeof( $( this ).attr( 'target' ) ) != 'undefined' ) {
            return true;
          }
          if ( typeof( $( this ).attr( 'onsubmit' ) ) == "undefined" ) {
            if ( $.fn.validate ) {
              validateForm( this );
            } else {
              $( this ).on( 'submit', function() {
                ajaxSubmitForm( this, function( request ) {
                  if ( request.success ) {
                    if ( typeof( options.submitCallback ) == 'function' ) {
                      options.submitCallback( request );
                    }
                    $( '#' + $dialog.dialogid ).modal( 'hide' );
                  }
                } );
                return false;
              } )
            }
          }
        } )
      }

      function load_url() {
        dialog_loaded();
        page_loaded();
        $( '#' + $dialog.dialogid ).find( 'a' ).click( function() {
          var url = $( this ).attr( 'href' );
          var re = /^#/;
          if ( typeof( $( this ).attr( 'onclick' ) ) != "undefined" || $( this ).attr( 'target' ) == '_blank' || re.test( url ) || url.substr( 0, 10 ).toLowerCase() == 'javascript' ) {
            return true;
          }
          $( '#' + $dialog.dialogid ).find( '.modal-body' ).load( url, function() {
            load_url();
          } );
          return false;
        } );
      }
      if ( $( '#' + $dialog.dialogid ).size() < 1 ) {
        $( '<div  class="modal" id="' + $dialog.dialogid + '"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button><h3 id="myModalLabel">' + options.title + '</h3></div><div class="modal-body">' + $dialog.loading_html + '</div></div></div></div>' ).appendTo( 'body' );
      } else {
        $( '#' + $dialog.dialogid ).find( '.modal-body' ).html( $dialog.loading_html );
      }
      $( '#' + $dialog.dialogid ).find( '.modal-body' ).css( 'max-height', $( window ).height() - 80 ).css( 'overflow-y', 'auto' );
      if ( postdata != null ) {
        $.ajax( {
          type: 'post',
          url: url,
          data: postdata,
          complete: function( XMLHttpRequest, textStatus ) {},
          success: function( html ) {
            if ( options.selector && $( html ).find( options.selector ).size() > 0 ) {
              $( '#' + $dialog.dialogid ).find( '.modal-body' ).html( $( html ).find( options.selector ).html() );
            } else {
              $( '#' + $dialog.dialogid ).find( '.modal-body' ).html( html );
            }
            load_url();
          },
          dataType: "html"
        } );
      } else {
        if ( options.selector ) {
          var obj = $( '#' + $dialog.dialogid ).find( '.modal-body' ).load( url + ' ' + options.selector, {}, function() {
            load_url();
          } );
        } else {
          var obj = $( '#' + $dialog.dialogid ).find( '.modal-body' ).load( url, {}, function() {
            load_url();
          } );
        }
      }
      if ( options.nobackdrop ) {
        $( '#' + $dialog.dialogid ).modal( {
          backdrop: false
        } );
      } else {
        $( '#' + $dialog.dialogid ).modal( {
          'backdrop': 'static',
          'keyboard': true
        } );
      }
      if ( options.width ) {
        $( '#' + $dialog.dialogid + ' .modal-dialog' ).width( options.width );
      }
      if ( options.zIndex ) {
        $( '#' + $dialog.dialogid ).css( 'z-index', options.zIndex );
      }
      return false;
    },
    load_url: function( url, selector ) {
      var $dialog = this;
      var re = /^#/;
      if ( re.test( url ) || url.substr( 0, 10 ).toLowerCase() == 'javascript' ) {
        return false;
      }
      if ( selector ) {
        url += ' ' + selector;
      }
      $( '#' + $dialog.dialogid ).load( url, function() {
        $( '#' + $dialog.dialogid ).find( 'a' ).click( function() {
          $dialog.load_url( $( this ).attr( 'href' ), {} );
          return false;
        } );
        page_loaded();
      } );
    },
    focus_close: function() {
      if ( this.dialogid ) {
        $( '#' + this.dialogid ).find( '.modal-header .close' ).focus();
      }
    },
    remove: function() {
      if ( this.dialogid ) {
        $( '.modal-backdrop' ).remove();
        $( '#' + this.dialogid ).remove();
      }
    },
    close_dialog: function() {
      if ( this.dialogid ) {
        $( '#' + this.dialogid ).modal( 'hide' );
        $( '.modal-backdrop' ).remove();
      }
    },
    open_msg_dialog: function( dialogid, title, content ) {
      $( '<div  class="modal fade" id="' + dialogid + '"><div class="modal-dialog"><div class="modal-content"><div class="modal-header">' + title + '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button><h3 id="myModalLabel"></h3></div><div class="modal-body">' + content + '</div></div></div></div>' ).appendTo( 'body' );
      $( '#' + dialogid ).modal( 'show' );
      $( '#' + dialogid ).on( 'hidden.bs.modal', function( e ) {
        $( '#' + dialogid ).remove();
      } );
    },
    open_html_dialog: function( dialogid, title ) {
      this.dialogid = dialogid;
      if ( $( '#' + this.dialogid ).size() < 1 ) {
        $( '<div  class="modal fade" id="' + this.dialogid + '"><div class="modal-dialog"><div class="modal-content"><div class="modal-header">' + title + '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button><h3 id="myModalLabel"></h3></div><div class="modal-body"></div></div></div></div>' ).appendTo( 'body' );
      }
      $( '#' + dialogid ).modal( {
        'backdrop': 'static',
        'keyboard': false
      } );
    },
    invite_tabs: {}
  };

  /*function inner_open( container_selector, result_selector ) {
  	$( container_selector ).find( 'a' ).click( function() {
  		var url = $( this ).attr( 'href' );
  		if ( result_selector ) {
  			url = url + ' ' + result_selector;
  		}
  		var re = /^#/;
  		if ( typeof( $( this ).attr( 'onclick' ) ) != "undefined" || $( this ).attr( 'target' ) == '_blank' || re.test( url ) || url.substr( 0, 10 ).toLowerCase() == 'javascript' ) {
  			return true;
  		}
  		$( container_selector ).scrollTop( 0 ).prepend( '<div style="margin:10px;"><img src="http://static.135editor.com/img/ajax/circle_ball.gif"> 正在加载内容...</div>' ).load( url, function() {
  			page_loaded();
  			inner_open( container_selector, result_selector );
  		} );
  		return false;
  	} );
  }*/

  /*function follow_wx( id ) {
  	var url = BASEURL + '/user_follows/follow/' + id;
  	if ( !sso.check_userlogin( {
  			"callback": follow_wx,
  			"callback_args": arguments
  		} ) )
  		return false;
  	publishController.open_dialog( url, {
  		'title': 'Follow',
  		width: 400
  	} );
  	return false;
  }*/

  /*function addtofavor( model, id, obj, callback ) {
  	var url = BASEURL + '/favorites/add/';
  	var postdata = {
  		'data[Favorite][model]': model,
  		'data[Favorite][data_id]': id
  	};
  	if ( !sso.check_userlogin( {
  			"callback": addtofavor,
  			"callback_args": arguments
  		} ) )
  		return false;
  	var evt = window.event || arguments.callee.caller.arguments[ 0 ];
  	evt.stopPropagation();
  	if ( typeof( callback ) == 'function' ) {
  		ajaxAction( url, postdata, null, callback );
  	} else {
  		ajaxAction( url, postdata, null, function( request ) {
  			if ( request.success ) {
  				if ( obj ) {
  					$( obj ).attr( 'disabled', 'disabled' ).removeClass( 'text-primary' ).addClass( 'text-success' );
  					if ( $( obj ).find( '.fa-heart-o' ).size() > 0 ) {
  						$( obj ).find( '.fa-heart-o' ).removeClass( 'fa-heart-o' ).addClass( 'fa-heart' );
  					}
  				}
  				var num_selector = '#Stats-' + request.data.model + '-' + request.data.data_id + '-favor_nums';
  				if ( $( num_selector ).size() > 0 ) {
  					var num = $( num_selector ).html();
  					num = num.replace( /\(|\)/g, '' );
  					if ( num == '' ) num = 0;
  					num = parseInt( num );
  					num++;
  					$( num_selector ).html( num );
  				}
  			}
  		} );
  	}
  	return false;
  }*/

  /*function unfavorite( obj, callback ) {
  	var evt = window.event || arguments.callee.caller.arguments[ 0 ];
  	evt.stopPropagation();
  	if ( !confirm( $.jslanguage.cancel_fav_confirm ) ) {
  		return false;
  	}
  	var url = $( obj ).data( 'url' );
  	if ( !sso.check_userlogin( {
  			"callback": unfavorite,
  			"callback_args": arguments
  		} ) )
  		return false;
  	ajaxAction( url, null, null, function( request ) {
  		if ( request.success ) {
  			if ( typeof( callback ) == 'function' ) {
  				callback( request );
  			}
  			$( obj ).attr( 'disabled', 'disabled' );
  			if ( $( obj ).find( '.fa-heart' ).size() > 0 ) {
  				$( obj ).find( '.fa-heart' ).removeClass( 'fa-heart' ).addClass( 'fa-heart-o' );
  			} else {
  				$( obj ).parents( 'li:first' ).remove();
  			}
  		}
  	} );
  	return false;
  }*/

  /*function refreshfavorite( obj ) {
  	var evt = window.event || arguments.callee.caller.arguments[ 0 ];
  	evt.stopPropagation();
  	var url = $( obj ).data( 'url' );
  	if ( !sso.check_userlogin( {
  			"callback": refreshfavorite,
  			"callback_args": arguments
  		} ) )
  		return false;
  	ajaxAction( url, null, null, function( request ) {
  		if ( request.ret == 0 ) {
  			$( obj ).parents( 'li:first' ).prependTo( $( obj ).parents( 'ul:first' ) );
  		}
  	} );
  	return false;
  }*/

  /*function addtoCart( id, num, model ) {
  	if ( !model ) {
  		model = 'product';
  	}
  	var url = BASEURL + '/carts/add';
  	var postdata = {
  		'data[Cart][num]': num,
  		'data[Cart][product_id]': id,
  		'data[Cart][product_model]': model
  	};
  	if ( !sso.check_userlogin( {
  			"callback": addtoCart,
  			"callback_args": arguments
  		} ) )
  		return false;
  	ajaxAction( url, postdata, null, 'addtoCart' );
  	return false;
  }*/

  /*function directBuy( id, num, model ) {
  	if ( !model ) {
  		model = 'product';
  	}
  	var url = BASEURL + '/carts/add?redirect=/orders/info&ck_ids=' + id;
  	var postdata = {
  		'data[Cart][num]': num,
  		'data[Cart][product_id]': id,
  		'data[Cart][product_model]': model
  	};
  	if ( !sso.check_userlogin( {
  			"callback": directBuy,
  			"callback_args": arguments
  		} ) )
  		return false;
  	ajaxAction( url, postdata, null, function() {
  		location.href = BASEURL + '/orders/info';
  	} );
  	return false;
  }*/

  /*function loadDiggData() {
  	var models = [];
  	var ids = {};
  	$( '.ui-dig-num' ).each( function( i ) {
  		var info = this.id.split( '-' );
  		if ( $.inArray( info[ 1 ], models ) < 0 ) {
  			models[ models.length ] = info[ 1 ];
  		}
  		if ( !ids[ info[ 1 ] ] ) {
  			ids[ info[ 1 ] ] = [];
  		}
  		if ( $.inArray( info[ 2 ], ids[ info[ 1 ] ] ) < 0 ) {
  			var id_length = ids[ info[ 1 ] ].length;
  			ids[ info[ 1 ] ][ id_length ] = info[ 2 ];
  		}
  	} );
  	for ( var i in models ) {
  		var model = models[ i ];
  		var data_id = ids[ models ];
  		loadModelDataDigg( model, data_id );
  	}
  }*/

  /*function loadModelDataDigg( model, data_id ) {
  	$.ajax( {
  		type: 'get',
  		url: BASEURL + '/appraiseresults/getdigdata',
  		data: {
  			'model': model,
  			'data_id': data_id
  		},
  		success: function( data ) {
  			for ( var i in data ) {
  				setDiggNum( data[ i ][ 'Appraiseresult' ] );
  			}
  		},
  		dataType: 'json'
  	} );
  }*/

  /*function loadStatsData() {
  	var models = [];
  	var ids = {};
  	$( '.ui-stats-num' ).each( function( i ) {
  		var s = this.id;
  		var info = s.split( '-' );
  		if ( $.inArray( info[ 1 ], models ) < 0 ) {
  			models[ models.length ] = info[ 1 ];
  		}
  		if ( !ids[ info[ 1 ] ] ) {
  			ids[ info[ 1 ] ] = [];
  		}
  		if ( $.inArray( info[ 2 ], ids[ info[ 1 ] ] ) < 0 ) {
  			var id_length = ids[ info[ 1 ] ].length;
  			ids[ info[ 1 ] ][ id_length ] = info[ 2 ];
  		}
  	} );
  	for ( var i in models ) {
  		var model = models[ i ];
  		var data_id = ids[ model ];
  		if ( model && model != "" ) {
  			loadModelDataStats( model, data_id );
  		}
  	}
  }

  function loadModelDataStats( model, data_id ) {
  	$.ajax( {
  		type: 'get',
  		url: BASEURL + '/stats_days/getdata',
  		data: {
  			'model': model,
  			'data_id': data_id
  		},
  		success: function( data ) {
  			for ( var i in data ) {
  				setStatsNum( data[ i ][ 'StatsDay' ] );
  			}
  		},
  		dataType: 'json'
  	} );
  }

  function setStatsNum( data ) {
  	if ( parseInt( data.favor_nums ) > 0 ) {
  		var id = '#Stats-' + data.model + '-' + data.data_id + '-favor_nums';
  		setQuoteNum( id, data.favor_nums );
  	}
  	if ( parseInt( data.comment_nums ) > 0 ) {
  		var id = '#Stats-' + data.model + '-' + data.data_id + '-comment_nums';
  		setQuoteNum( id, data.comment_nums );
  	}
  	if ( parseInt( data.view_nums ) > 0 ) {
  		var id = '#Stats-' + data.model + '-' + data.data_id + '-view_nums';
  		setQuoteNum( id, data.view_nums );
  	}
  }

  function setQuoteNum( select, value ) {
  	if ( $( select ).size() > 0 ) {
  		var num = $( select ).eq( 0 ).html();
  		num = num.replace( /&nbsp;| /g, '' );
  		num = num.replace( /\(|\)/g, '' );
  		if ( num == '' ) num = 0;
  		num = parseInt( num );
  		num = num + parseInt( value );
  		$( select ).html( num );
  	}
  }*/

  /*function loadModelDataMood( model, data_id ) {
  	$.ajax( {
  		type: 'get',
  		url: BASEURL + '/appraiseresults/getdigdata',
  		data: {
  			'model': model,
  			'data_id': data_id
  		},
  		success: function( data ) {
  			var total = 0;
  			for ( var i in data ) {
  				if ( data[ i ][ 'Appraiseresult' ].question_id == 3 ) {
  					total += parseInt( data[ i ][ 'Appraiseresult' ].value );
  				}
  			}
  			for ( var i in data ) {
  				setDiggNum( data[ i ][ 'Appraiseresult' ], total );
  			}
  		},
  		dataType: 'json'
  	} );
  }*/

  /*function loadComments( model, id ) {
  	$.get( BASEURL + '/comments/get_comments_data/' + model + '/' + id, {}, function( comments ) {
  		var current = null;
  		var commentstarget = '.comments-' + model + '-' + id;
  		$( commentstarget ).html( '' );
  		for ( var i = 0; i < comments.length; i++ ) {
  			current = comments[ i ].Comment;
  			var comment_html = '<li><span class="t">' + current.name + '  ' + current.created + '</span><p>' + current.body + '</p><li>';
  			$( commentstarget ).append( comment_html );
  		}
  	}, "json" );
  }

  function loadMoodDigg( model, id ) {
  	$.get( BASEURL + '/appraises/load/3/' + id + '/' + model + '?inajax=1', {}, function( MoodData ) {
  		$( '#mood-' + model + '-' + id ).html( MoodData );
  	}, "html" );
  }*/
  /*var page_hash = {
  	storedHash: '',
  	currentTabHash: '',
  	cache: '',
  	interval: null,
  	listen: true,
  	startListening: function() {
  		setTimeout( function() {
  			page_hash.listen = true;
  		}, 600 );
  	},
  	stopListening: function() {
  		page_hash.listen = false;
  	},
  	checkHashChange: function() {
  		var locStr = page_hash.currHash();
  		if ( page_hash.storedHash != locStr ) {
  			if ( page_hash.listen == true ) page_hash.refreshToHash();
  			page_hash.storedHash = locStr;
  		}
  		if ( !page_hash.interval ) page_hash.interval = setInterval( page_hash.checkHashChange, 500 );
  	},
  	refreshToHash: function( locStr ) {
  		if ( locStr ) var newHash = true;
  		locStr = locStr || page_hash.currHash();
  		var hash_array = locStr.split( '&' );
  		for ( var i in hash_array ) {
  			var pageinfo = hash_array[ i ].split( '=' );
  			if ( pageinfo[ 0 ] && pageinfo[ 1 ] && pageinfo[ 0 ].substr( 0, 5 ) == 'page_' ) {
  				var portletid = pageinfo[ 0 ].replace( 'page_', '' );
  				var page = pageinfo[ 1 ];
  				$( '.page_' + page, '#' + portletid ).trigger( 'click' );
  			}
  		}
  		if ( newHash ) {
  			page_hash.updateHash( locStr, true );
  		}
  	},
  	updateHash: function( locStr, ignore ) {
  		if ( ignore == true ) {
  			page_hash.stopListening();
  		}
  		window.location.hash = locStr;
  		if ( ignore == true ) {
  			page_hash.storedHash = locStr;
  			page_hash.startListening();
  		}
  	},
  	clean: function( locStr ) {
  		return locStr.replace( /%23/g, "" ).replace( /[\?#]+/g, "" );
  	},
  	currHash: function() {
  		return page_hash.clean( window.location.hash );
  	},
  	currSearch: function() {
  		return page_hash.clean( window.location.search );
  	},
  	init: function() {
  		page_hash.storedHash = '';
  		page_hash.checkHashChange();
  	}
  };*/

  /*function Html5Uploadfile( file_id ) {
  	this.file_input = null;
  	var uploading_id = file_id + randomString( 10 );
  	this.upload = function( file_input, options ) {
  		this.file_input = file_input;
  		var file = file_input.files[ 0 ];
  		if ( file ) {
  			var fileSize = 0;
  			if ( file.size > 1024 * 1024 )
  				fileSize = ( Math.round( file.size * 100 / ( 1024 * 1024 ) ) / 100 ).toString() + 'MB';
  			else
  				fileSize = ( Math.round( file.size * 100 / 1024 ) / 100 ).toString() + 'KB';
  			var fd = new FormData();
  			fd.append( "file_post_name", options.file_post_name );
  			fd.append( "file_model_name", options.file_model_name );
  			fd.append( "no_db", options.no_db );
  			fd.append( "data_id", options.data_id );
  			fd.append( "item_css", options.item_css );
  			fd.append( "save_folder", options.save_folder );
  			fd.append( "return_type", options.return_type );
  			fd.append( options.file_post_name, file );
  			this.uploading_files[ options.file_post_name ] = {};
  			this.uploading_files[ options.file_post_name ][ file.name ] = true;
  			var append_html = '<div id="' + uploading_id + '-status" class="uploading-item clearfix"><span class="filename">' + file.name + '</span> <div class="progress pull-left" style="width:200px;">' + '<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width:0%">' + '<span class="sr-only">0%</span>' + '</div></div> </div>';
  			$( file_input ).after( append_html );
  			var xhr = new XMLHttpRequest();
  			xhr.upload.addEventListener( "progress", this.uploadProgress, false );
  			xhr.addEventListener( "load", this.uploadComplete, false );
  			xhr.addEventListener( "error", this.uploadFailed, false );
  			xhr.addEventListener( "abort", this.uploadCanceled, false );
  			xhr.open( "POST", options.upload_url );
  			xhr.send( fd );
  		}
  	}, this.uploading_files = {}, this.check_upload = function() {
  		return false;
  	}, this.uploadProgress = function( evt ) {
  		if ( evt.lengthComputable ) {
  			var percentComplete = Math.round( evt.loaded * 100 / evt.total );
  			$( '#' + uploading_id + '-status' ).find( '.progress-bar' ).css( 'width', percentComplete.toString() + '%' );
  		} else {
  			alert( 'Unable to compute.Please retry.' );
  		}
  	}, this.uploadComplete = function( evt ) {
  		var data = eval( '(' + evt.target.responseText + ')' );
  		$( '#fileuploadinfo_' + data.fieldname ).append( data.message );
  		$( '#' + uploading_id + '-status' ).fadeOut( "slow" ).remove();
  	}, this.uploadFailed = function( evt ) {
  		alert( "There was an error attempting to upload the file." );
  	}, this.uploadCanceled = function( evt ) {
  		alert( "The upload has been canceled by the user or the browser dropped the connection." );
  	};
  }*/

  /*function debug_object( obj ) {
  	var str = '';
  	for ( var i in obj ) {
  		str += i + '=' + obj[ i ] + ";\t";
  	}
  	$( 'body' ).append( '<hr/>' + str );
  }

  function getAvatarUrl( uid ) {
  	return BASEURL + '/files/avatar/' + parseInt( uid / 1000 % 1000 ) + '/' + parseInt( uid % 1000 ) + '/' + uid + '_0.jpg';
  }*/
  /*$( function() {
  	$( '.nav .dropdown,.navbar-nav .dropdown,header .dropdown' ).hover( function( e ) {
  		$( this ).addClass( 'open' );
  	}, function() {
  		$( this ).removeClass( 'open' );
  	} ).click( function( e ) {
  		e.stopPropagation();
  	} );
  	/*if ( $.fn.validate ) {
  		jQuery.validator.addMethod( "biggerThen", function( value, element ) {
  			var biggerThan = $( element ).attr( 'biggerThen' );
  			var type = $( element ).data( 'type' );
  			if ( type == 'string' ) {
  				return value > $( biggerThan ).val();
  			} else {
  				return parseInt( value ) > parseInt( $( biggerThan ).val() );
  			}
  		}, "Please check the value is in the right range" );
  		$( 'form' ).each( function() {
  			validateForm( this );
  		} )
  	}*/
  /*if ( $( '#ajaxestatus' ).size() > 0 ) {
  	$( document ).ajaxStart( function() {
  		$( '#ajaxestatus' ).show();
  	} ).ajaxStop( function() {
  		$( '#ajaxestatus' ).hide();
  	} );
  }*/
  /*$( document ).on( 'click.bs.collapse.data-api', '.collapse-itemmenu > a', function( e ) {
  	var $this = $( this );
  	e.preventDefault();
  	$this.parents( '.collapse-itemmenu:first' ).toggleClass( 'open' );
  	if ( $this.find( '.glyphicon-plus' ).size() > 0 ) {
  		$this.find( '.glyphicon-plus' ).addClass( 'glyphicon-minus' ).removeClass( 'glyphicon-plus' );
  	} else {
  		$this.find( '.glyphicon-minus' ).addClass( 'glyphicon-plus' ).removeClass( 'glyphicon-minus' );
  	}
  } );*/
  /*$( '.collapse-menu > li.open' ).each( function() {
  	$( this ).find( 'a:first>.glyphicon-plus' ).addClass( 'glyphicon-minus' ).removeClass( 'glyphicon-plus' );
  } );*/
  /*$( document ).on( 'click', '.upload-fileitem .remove', function() {
			if ( !confirm( 'Are you sure to delete this file.' ) ) {
				return false;
			}
			var $this = $( this );
			var data_id = $( this ).data( 'id' );
			$.ajax( {
				type: 'post',
				url: BASEURL + '/uploadfiles/delete',
				data: {
					id: data_id
				},
				success: function( data ) {
					if ( data.error ) {
						alert( data.error );
						return false;
					} else {
						$this.parents( '.upload-fileitem:first' ).remove();
					}
				},
				dataType: 'json'
			} );
		} );
		loadStatsData();
	} );*/

  /*function getUnreadMsgNum() {
  	$.ajax( {
  		type: 'get',
  		url: BASEURL + '/shortmessages/unreadnum/',
  		success: function( data ) {
  			var num = parseInt( data );
  			if ( num > 0 ) {
  				$( '.user-unread-msgnum' ).html( data ).show();
  			}
  		},
  		dataType: 'html'
  	} );
  }*/
  /*var stack_custom = {
  	"dir1": "right",
  	"dir2": "down"
  };*/

  /*function validateForm( form ) {
  	if ( typeof( $( form ).attr( 'onsubmit' ) ) != 'undefined' || typeof( $( form ).data( 'noajax' ) ) != 'undefined' || typeof( $( form ).attr( 'target' ) ) != 'undefined' || $( form ).attr( 'method' ) == 'get' || $( form ).attr( 'method' ) == 'GET' ) {
  		return true;
  	}
  	var validator = $( form ).validate( {
  		errorElement: 'span',
  		errorClass: 'help-block',
  		focusInvalid: true,
  		highlight: function( element ) {
  			$( element ).closest( '.form-group' ).addClass( 'has-error' );
  		},
  		success: function( label ) {
  			label.closest( '.form-group' ).removeClass( 'has-error' );
  			label.remove();
  		},
  		errorPlacement: function( error, element ) {
  			element.parent( 'div' ).append( error );
  		},
  		submitHandler: function( form ) {
  			if ( $( form ).validate().form() ) {
  				if ( typeof( $( form ).data( 'noajax' ) ) != 'undefined' || typeof( $( form ).attr( 'target' ) ) != 'undefined' || $( form ).attr( 'method' ) == 'get' || $( form ).attr( 'method' ) == 'GET' ) {
  					return true;
  				} else {
  					ajaxSubmitForm( form );
  				}
  			}
  		}
  	} );
  	return validator;
  }*/

  /*function randomString( len ) {
  	len = len || 8;
  	var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
  	var maxPos = $chars.length;
  	var pwd = '';
  	for ( i = 0; i < len; i++ ) {
  		pwd += $chars.charAt( Math.floor( Math.random() * maxPos ) );
  	}
  	return pwd;
  }*/

  function strtolower( str ) {
    return ( str + '' ).toLowerCase();
  }

  function substr( str, start, len ) {
    var i = 0,
      allBMP = true,
      es = 0,
      el = 0,
      se = 0,
      ret = '';
    str += '';
    var end = str.length;
    this.php_js = this.php_js || {};
    this.php_js.ini = this.php_js.ini || {};
    switch ( ( this.php_js.ini[ 'unicode.semantics' ] && this.php_js.ini[ 'unicode.semantics' ].local_value.toLowerCase() ) ) {
      case 'on':
        for ( i = 0; i < str.length; i++ ) {
          if ( /[\uD800-\uDBFF]/.test( str.charAt( i ) ) && /[\uDC00-\uDFFF]/.test( str.charAt( i + 1 ) ) ) {
            allBMP = false;
            break;
          }
        }
        if ( !allBMP ) {
          if ( start < 0 ) {
            for ( i = end - 1, es = ( start += end ); i >= es; i-- ) {
              if ( /[\uDC00-\uDFFF]/.test( str.charAt( i ) ) && /[\uD800-\uDBFF]/.test( str.charAt( i - 1 ) ) ) {
                start--;
                es--;
              }
            }
          } else {
            var surrogatePairs = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
            while ( ( surrogatePairs.exec( str ) ) != null ) {
              var li = surrogatePairs.lastIndex;
              if ( li - 2 < start ) {
                start++;
              } else {
                break;
              }
            }
          }
          if ( start >= end || start < 0 ) {
            return false;
          }
          if ( len < 0 ) {
            for ( i = end - 1, el = ( end += len ); i >= el; i-- ) {
              if ( /[\uDC00-\uDFFF]/.test( str.charAt( i ) ) && /[\uD800-\uDBFF]/.test( str.charAt( i - 1 ) ) ) {
                end--;
                el--;
              }
            }
            if ( start > end ) {
              return false;
            }
            return str.slice( start, end );
          } else {
            se = start + len;
            for ( i = start; i < se; i++ ) {
              ret += str.charAt( i );
              if ( /[\uD800-\uDBFF]/.test( str.charAt( i ) ) && /[\uDC00-\uDFFF]/.test( str.charAt( i + 1 ) ) ) {
                se++;
              }
            }
            return ret;
          }
          break;
        }
      case 'off':
      default:
        if ( start < 0 ) {
          start += end;
        }
        end = typeof len === 'undefined' ? end : ( len < 0 ? len + end : len + start );
        return start >= str.length || start < 0 || start > end ? !1 : str.slice( start, end );
    }
    return undefined;
  };

} );